数据降维及可视化之TSNE理论及利用sklearn对digits数据集可视化实现python

今天来简单总结一下TSNE~

SNE

首先来说说SNE,全称为随机相邻嵌入(Stochastic Neighbor Embedding),其将数据之间的高维的欧几里得距离转化为表示相似性的条件概率:数据点

xjx_j

xj?与数据点

xix_i

xi?的相似性表示为条件概率的样子

pjip_{j|i}

pj∣i?,表达为

xix_i

xi?选择

xjx_j

xj?作为邻居,表达式为:

pji=exp(?xi?xj2/2σi2)kiexp(?xi?xk2/2σi2)
p_{j|i}=\frac{exp(-||x_i-x_j||^2/2\sigma_i^2)}{\sum_{k\neq i}exp(-||x_i-x_k||^2/2\sigma_i^2)}

pj∣i?=∑k?=i?exp(?∣∣xi??xk?∣∣2/2σi2?)exp(?∣∣xi??xj?∣∣2/2σi2?)?
其中

σi\sigma_i

σi?是

xix_i

xi?为中心的高斯分布的方差。(

pii=0p_{i|i}=0

pi∣i?=0)
当我们把高维数据映射到低维空间中时,我们要保证其数据分布应与原来的相同,或者说是数据点之间的相似性相同。那么设刚刚数据点

xjx_j

xj?与数据点

xix_i

xi?对应的低维中的数据点为

yjy_j

yj?与

yiy_i

yi?,他们之间的相似度为:

qji=exp(?yi?yj2)kiexp(?xi?xk2)
q_{j|i}=\frac{exp(-||y_i-y_j||^2)}{\sum_{k\neq i}exp(-||x_i-x_k||^2)}

qj∣i?=∑k?=i?exp(?∣∣xi??xk?∣∣2)exp(?∣∣yi??yj?∣∣2)?
同样,(

qii=0q_{i|i}=0

qi∣i?=0)
所以,我们的目标就是尽可能地让这两个条件概率相等。利用KL三度给出损失函数C:

C=iKL(PiQi)=ijpjilog(pjiqji)
C=\sum_i KL(P_i||Q_i)=\sum_i\sum_j p_{j|i}log(\frac{p_{j|i}}{q_{j|i}})

C=i∑?KL(Pi?∣∣Qi?)=i∑?j∑?pj∣i?log(qj∣i?pj∣i??)
这样做有个缺点,由于KL散度的不对称性质,因此低维空间中成对距离的不同类型的误差权重并不相等。 尤其是,使用小的

qjiq_{j|i}

qj∣i?来模拟大的

pjip_{j|i}

pj∣i?存在巨大的损失,但是使用低维空间中的相近的数据点代表高维空间中相互分离的数据点仅造成很小的损失,这就造成了一些分类异常的情况。SNE损失函数C着重于保留数据的局部结构,而非全局结构。
损失函数利用梯度下降法迭代,梯度为:

?C?yi=2j(pji?qji+pij?qij)(yi?yj)
\frac{\partial C}{\partial y_i}=2\sum_j (p_{j|i}-q_{j|i}+p_{i|j}-q_{i|j})(y_i
-y_j)

?yi??C?=2j∑?(pj∣i??qj∣i?+pi∣j??qi∣j?)(yi??yj?)

拥挤问题

对于拥挤问题,我们举例进行说明。我们都知道,n+1个数据点在n维空间中可能存在相互等距的情况,导致这n+1个数据点没有办法在更低维的空间中真实地建模。我们假设,一个球体将

xix_i

xi?作为球体的中心点,其球体的半径为r,其m维的球体的体积为

rmr_m

rm?,假设在十维空间上的流形图上,数据点呈均匀分布的趋势,我们采用Python来模拟二维空间中数据点

xix_i

xi?到其余数据点的距离,得到下面的“拥挤问题”:
点到圆心的距离不同的点的个数
图中横坐标表示数据点到圆心的距离,纵坐标表示数据点的数量。由图可以清楚地看出,大部分流形上的数据点都随着维度的增大而聚集在m球的表面,分布并不均衡。如果这种距离关系直接被保留到低维空间中,则一定会出现上述拥挤问题。

T分布的长尾特性

t分布会随着自由度的增大而逐渐趋近于标准正态分布,当自由度趋近于无穷大时,我们可以用正态分布的概率密度函数去近似t分布的概率密度公式。
t分布不同自由度下的分布图和正态分布分布图
顶端黑色曲线是正态分布曲线,下方红色曲线是自由度为1的t分布曲线,两条曲线之间的众多曲线是t分布随着自由度增加而升高的曲线。从图中我们可以看出t分布比正态分布的尾端更为平缓,这就是t分布的长尾特性。
有无异常点的情况下t分布与正态分布的概率密度函数
上方图中无异常点时,正态分布与t分布的拟合结果基本一致。但是出现部分异常点的图中,由于t分布对异常点的不敏感性,更好地保留了原始数据的整体特征。相比较而言,正态分布对异常点更为敏感,而且的尾部较低,这使得正态分布的方差较大,因此其拟合结果并不理想。所以t分布拥有正态分布没有的一个特性:可以排除异常值对其拟合的干扰

TSNE

其中TSNE分为T和SNE:T表示t分布,SNE表示对称的SNE。对称的条件概率:

pij=(pji+pij)/2n
p_{ij}=(p_{j|i}+p_{i|j})/2n

pij?=(pj∣i?+pi∣j?)/2n
得到对称的SNE模型梯度:

?C?yi=4j(pij?qij)(yi?yj)
\frac{\partial C}{\partial y_i}=4\sum_j (p_{ij}-q_{ij})(y_i-y_j)

?yi??C?=4j∑?(pij??qij?)(yi??yj?)
对称的SNE模型匹配了高维与低维空间中的联合概率,但实际上并没有匹配高维与低维空间中的距离,所以对称的SNE模型并没有从根本上解决拥挤问题,所以我们将利用t分布去缓解如下的拥挤问题。
定义联合概率:

qij=(1+yi?yj2)?1kl(1+yk?yl2)?1
q_{ij}=\frac{(1+||y_i-y_j||^2)^{-1}}{\sum_{k\neq l}(1+||y_k-y_l||^2)^{-1}}

qij?=∑k?=l?(1+∣∣yk??yl?∣∣2)?1(1+∣∣yi??yj?∣∣2)?1?
TSNE的迭代梯度:

?C?yi=4j(pij?qij)(yi?yj)(1+yi?yj2)?1
\frac{\partial C}{\partial y_i}=4\sum_j (p_{ij}-q_{ij})(y_i-y_j)(1+||y_i-y_j||^2)^{-1}

?yi??C?=4j∑?(pij??qij?)(yi??yj?)(1+∣∣yi??yj?∣∣2)?1
在这里插入图片描述
展示了对称的SNE、UNI-SNE和TSNE三个模型中两个低维空间数据点之间的梯度来模拟它们在高维和低维空间中的距离函数。其中,梯度的正值表示低维空间中数据点之间的吸引作用,而负值表示排斥作用。从图中,我们可以观察到T-SNE的梯度对比于对称的SNE和UN-SNE的梯度的两个主要优点:

  • 首先,TSNE梯度强烈地排斥了一些不相似的数据点,这些不相似的数据点是低维空间中对应的小的成对距离拟合造成的。
  • 其次,虽然TSNE在小的成对距离模拟的不同数据点之间引入了非常强烈的排斥,但这些排斥并不是无用的。

总之,TSNE着重强调通过大的成对距离拟合不相似的数据点,并且通过小的成对距离拟合相似的数据点。

测试

采用Sklearn中的digits数据集,其中该数据集共包含1760个样本,包含10类,每个数据含有8*8个特征。我们利用sklearn中的tsne测试:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import matplotlib
import matplotlib.pyplot as plt
def test_digits():
    import pandas as pd
    import time
    import matplotlib
    import matplotlib.pyplot as plt
    from sklearn.manifold import TSNE
    from sklearn import datasets
    data=datasets.load_digits()
    target=data.target
    color=['yellow','black','green','red','blue','orange','brown','pink','purple','grey']
    t1=time.time()
    Y1=TSNE(n_components=2,learning_rate=100).fit_transform(data.data)
    t2=time.time()
    t=t2-t1
    print("Sklearn KL-TSNE cost time: %s"%str(round(t,2)))
    for i in range(10):
        xxx1=Y1[target==i,0]
        xxx2=Y1[target==i,1]
        plt.scatter(xxx1,xxx2,c=color[i])
    plt.xlim(numpy.min(Y1)-5,numpy.max(Y1)+5)
    plt.xlim(numpy.min(Y1)-5,numpy.max(Y1)+5)
    plt.title('KL-SKLEARN: %ss'%str(round(t,2)))
    plt.show()
test_digits()

在这里插入图片描述