【数据可视化】SNE
遇到了t分布。
这学期正巧选了一门数据可视化的课程,不过似乎老师并没有打算讲数学原理方面的东西,而纯粹是以工程的角度秀自己之前的成果……因此也不期望从课上学到什么。但还是在老师的PPT上看到了一些酷炫的数据可视化的图片。一直好奇一些论文中漂亮的散点图是怎么绘制的,比如像下面这种将Fashion MNSIT种的10种衣物一齐展示在一张图上,并且物以类聚,简洁明了。
之前猜测这种图可能是用到了PCA或者Kmeans这些方式,比如先用某个“黑盒子”提取出几种特征,然后再使用PCA筛选最终展示效果规定的维度(比如上面这个例子就是2维),如果使用神经网络的话,似乎直接用全连接层控制输出的维度就好了。不过关于这种猜测并没有真正实践(狗头)。后来在看CS224N的时候,Christopher Manning老师正好提到了t-SNE,于是就开始了这趟递归学习……
SNE
SNE的全称是stochastic neighbor embedding,而且是Hinton提出的。看到“stochastic”和“embedding”的第一感觉就是这个算法一定是某种迭代优化的算法,而不是一种直接映射的方式。
算法的目的是将高维数据分布的特点迁移到低维数据上,如果两个点在高维空间靠近的话,那么在映射到低维空间时,这两个点的距离也应当是靠近的。
先是如何衡量高维上的靠近。最简单的是算出每一对点的距离,不过Hinton并没有这么做,而是使用另一种衡量方式。假设高维上有两个点$x_i$和点$x_j$,定义点i靠近点j的程度为
$$
p_{j|i} = \frac{exp(-\left|x_i-x_j\right|^2/2\sigma_i^2)}{\sum_{k \neq i}{exp(-\left|x_i-x_k\right|^2/2\sigma_i^2)}}
$$
$\sigma_i$表示以$x_i$为中心的高斯分布的方差。
从这个式子可以看出这个式子定义的靠近是概率意义上的,并且这种所谓的靠近并不对称,因为$p_{j|i} \neq p_{i|j}$,就好像KL散度的非对称性一样。实际上之后的损失函数的确用到了KL散度。
然后,高维点集X要被映射到低维上要进行可视化了,假设映射关系为$x_i \rightarrow y_i$。并且定义新点集距离分布为
$$
q_{j|i} = \frac{exp(-\left|y_i-y_j\right|^2)}{\sum_{k \neq i}{exp(-\left|y_i-y_k\right|^2)}}
$$
因为这里的分布是将要计算的,因此可以自定义分布的方差,简单起见就为$1/\sqrt{2}$好了,这样式子就不出现$\sigma$了。
将视角切换到点$x_i$上,点$x_i$到其他点的距离分布最终转化为了概率分布,不妨假设其为$P_i$;同理,低维空间的点$y_i$也拥有一个分布$Q_i$。如何衡量两个分布的相似程度?KL散度出现了。
定义损失函数为
$$
C = \sum_{i}KL(P_i|Q_i) = \sum_{i}{\sum_{j}{p_{j|i}\log{\frac{p_{j|i}}{q_{j|i}}}}}
$$
t-SNE
t-SNE是对SNE的改进。首先是 __对称问题__。因为KL散度是非对称的,KL(P|Q)一般不等于KL(Q|P),为了做到对称,简单的方法就是两者兼顾,即
$$
p_{ij} = \frac{p_{j|i} + p_{i|j}}{2n}
$$
n表示点的数量。这是高维空间的概率,低维空间的改进是考虑全局距离
$$
q_{ij} = \frac{exp(-\left|y_i-y_j\right|^2)}{\sum_{k \neq l}{exp(-\left|y_k-y_l\right|^2)}}
$$
和SNE的$q_{j|i}$对比一下,可以发现分母计算了每一对点的距离。
损失函数变为
$$
C = KL(P|Q) = \sum_{i}{\sum_{j}{p_{ij}\log{\frac{p_{ij}}{q_{ij}}}}}
$$
其次是 数据拥挤 的问题。考虑在n维空间上随机撒点,那么这些点距离原点的距离分布的问题。
1 | import numpy as np |
可以看出,随机点离原点的距离变化随着维度升高,是趋向于敏感的,高维空间点的分布更加集中。这会给直接降维带来麻烦,若不加处理直接将高维空间距离分布映射到低维空间,那么点会聚成一团;即使使用正则化“拉伸”这些点的距离,效果也不会很明显。
需要注意的是,点是随机撒的,那么无论是高维空间还是低维空间,空间中点的分布都是大致均匀的,并不存在挤成一团的问题。计算距离也算是一种降维处理,这里就能体现出简单降维处理存在的拥挤问题。
比较理想的处理方式是使用一种映射方式,让高维距离分布拥有低维距离分布“矮胖”的特点,这就用到了t-分布。
t-分布的自由度越低,曲线越矮。如果把高维空间的分布视为正态分布,将要映射的分布视为自由度为1的t-分布,就可以缓解数据拥挤的问题!这样,高维数据距离公式不需要变动,只需要将低维距离公式改变,让其满足t-分布的特点即可。
t-分布这种“矮胖”的身材还能很好的消除 小样本 中存在离群点的缺点。
$q_{ij}$的公式贴在下面。之所以使用自由度为1的t-分布,是因为这种形式符合“平方反比定律”,能够在低维空间中很好地表示巨多的点对之间的关系(作者说的:))。
$$
q_{ij} = \frac{(1 + \left|y_i-y_j \right|^2)^{-1}}{\sum_{k \neq l}{(1 + \left|y_k-y_l \right|^2)^{-1}}}
$$
衡量两个距离分布相似性还是使用KL散度。计算可以直接使用梯度计算
$$
\frac{\partial C}{\partial y_i} = 4 \sum_{j}{(p_{ij} - q_{ij})(y_i - y_j)(1 + \left|y_i - y_j\right|^2)^{-1}}
$$
最后说说t-SNE算法的缺点吧,其实缺点已经很明显了……和训练词向量一样,当数据量很大的时候,会算得很慢,并且每次训练的结果都是不一样的。为了解决速度的问题,有很多人尝试使用“树”结构来加速(比如kd-tree?),还有人使用“负采样”来加速,说到底也是想用小样本估计总体样本,虽然精度可能会出现偏差,不过反正训练出来的结果是给人看的,又何必在意一两个点的偏移呢?
词向量降维可视化
既然本篇是在学习CS224N的过程中深挖的产物,那么实验环节用词向量降维是再合适不过的了。通常使用的词向量动辄上百维,非常不适合碳基生物的理解,如果需要查看训练之后词向量表达意思的能力,至少需要将其降维到3维空间。
以GLOVE为例,glove.6B.50d
为高维数据,然后要将其投射到3维平面。该数据集有40w条预训练的词向量,每条词向量拥有50个维度。为了能比较清楚地看出词和词之间的关系,使用2维空间可视化这些向量(3维能显示更多的信息,但是显示效果容易受视角的影响)。
训练代码附在后面,训练结果如下:
代码
1 | import copy |