t-SNE 算法

1 前言

  t-SNE 即 t-distributed stochastic neighbor embedding 是一种用于降维的机器学习算法,在 2008 年由 Laurens van der Maaten 和 Geoffrey Hinton 提出。

  t-SNE 是一种非线性降维算法,主要适用于将高维数据降维到 2 维或 3 维 ,方便可视化。但是由于以下种种原因导致它不适合于降维,仅适合可视化:

  • 数据需要降维时,特征间常存在线性相关性,此时常使用线性降维算法,如 PCA。而对于特征之间存在非线性相关,我们并不会先使用非线性降维算法降维再搭配一个线性模型,而是直接使用非线性模型;
  • 一般而言,我们降维并不会把数据维度降维到2 维或者3维,降维的维度一般较大,如降到 20 维,由于 t-SNE 算法使用自由度为 1 的 t 分布很难做到好的效果;
  • t-SNE 算法计算复杂度很高,目标函数非凸,容易得到局部最优解;

  以下使用 t-SNE 和 PCA可视化手写数字的效果对比:

      

  常见的降维算法:

    • 主成分分析(线性)
    • t-SNE (非参数/非线性)
    • 萨蒙映射(非线性)
    • 等距映射(非线性)
    • 局部线性嵌入(非线性)
    • 规范相关分析(非线性)
    • SNE(非线性)
    • 最小方差无偏估计(非线性)
    • 拉普拉斯特征图(非线性)

2 SNE 算法

  t-SNE 算法是从 SNE 改进而来,所以先介绍 SNE 。给定一组高维数据 $ \{x_{1}, x_{2}, \ldots, x_{n} \} , x_i=(x_{i}^{(1)}$,$x_{i}^{(2)},x_{i}^{(3)},......x_{i}^{(n)}) $,目标是将这组数据降维到 2 维,SNE 的基本思想是若两个数据在高维空间中是相似的,那么降维到 2 维空间时距离得很近。

2.1 高维空间

  随机邻近嵌入(SNE) 采用首先通过将数据点之间的高维欧几里得距离转换为相似性的条件概率来描述两个数据之间的相似性。

  假设高维空间中的两个点 $ x_{i}, x_{j}$ ,以点 $ x_{i}$ 为中心构建方差为 $ \sigma_{i}$ 的高斯分布。用 $ p_{j \mid i}$ 表示 $ x_{j}$ 在 $ x_{i}$  邻域的概率,若 $ x_{j}$ 与 $ x_{i}$ 相距很近,那么 $ p_{j \mid i}$ 很大;反之, $ p_{j \mid i}$ 很小。

  $ p_{j \mid i}$ 定义如下:

    $p_{j \mid i}=\frac{\exp \left(-\left\|x_{i}-x_{j}\right\|^{2} /\left(2 \sigma_{i}^{2}\right)\right)}{\sum_{k \neq i} \exp \left(-\left\|x_{i}-x_{k}\right\|^{2} /\left(2 \sigma_{i}^{2}\right)\right)}$

  只关心不同点对之间的相似度,所以设 $p_{i \mid i}=0$ 。

2.2 低维空间

  当把数据映射到低维空间后,高维数据点之间的相似性也应该在低维空间的数据点上体现出来。  

  假设 $ x_{i}, x_{j}$ 映射到低维空间后对应 $ y_{i}, y_{j}$,那么 $y_{j}$ 是 $ y_{i}$ 邻域的条件概率为 $ q_{j \mid i}$ :

    $q_{j \mid i}=\frac{\exp \left(-\left\|y_{i}-y_{j}\right\|^{2}\right)}{\sum \limits _{k \neq i} \exp \left(-\left\|y_{i}-y_{k}\right\|^{2}\right)}$

  低维空间中的方差直接设置为  $ \sigma_{i}=\frac{1}{\sqrt{2}}  $ 。同样  $q_{i \mid i}=0$  。

2.3 目标函数

  若  $y_{i}$  和  $y_{j}$  真实反映了高维数据点  $x_{i}$  和  $x_{j}$  之间的关系,那么条件概率  $p_{j \mid i}$  与  $q_{j \mid i} $ 应该完全相等。这里只考虑了  $x_{i}$  与  $x_{j}$ 之间的条件概率,若考虑  $x_{i}$  与其他所有点之间的条件概率,则可构成一个条件概率分布  $P_{i}$。 同理在低维空间存在一个条件概率分布  $Q_{i}$  且应该与  $P_{i}$  对应。

  衡量两个分布之间的相似性采用 KL 距离(Kullback-Leibler Divergence),SNE 最终目标就是对所有数据点最小化 KL 距 离,我们使用梯度下降算法最小化如下代价函数:

    $C=\sum\limits_{i} K L\left(P_{i}|| Q_{i}\right)=\sum \limits _{i} \sum \limits_{j} p_{j \mid i} \log \frac{p_{j \mid i}}{q_{j \mid i}}$

  但由于 KL 距离 是一个非对称的度量。最小化代价函数的目的是让  $p_{j \mid i}$  和  $q_{j \mid i}$ 的值尽可能的接近,即低维空间中点的相似性应当与高维空间中点的相似性一致。但从代价函数的形式可以看出,当  $p_{j \mid i}$  较大,$q_{j \mid i}$  较小时,代价较高;而  $p_{j \mid i}$ 较小,$ q_{j \mid i}$ 较大时,代价较低。即高维空间中两个数据点距离较近时,若映射到低维空间后距离较远,那么将得到一个很高的惩罚,这当然没问题。反之,高维空间中两个数据点距离较远时,若映射到低维空间距离较近,将得到一个很低的惩罚值,显然应得到一个较高的惩罚。即SNE的代价函数更关注局部结构,而忽视了全局结构。

2.4 SNE缺点

  总结一下SNE的缺点:

  • 不对称导致梯度计算复杂。由于条件概率  $p_{j \mid i}$  不等于  $p_{i \mid j}$,$q_{j \mid i}$  不等于  $q_{i \mid j} $,因此梯度计算中需要的计算量较大。目标函数计算梯度如下:

    $\frac{\delta C}{\delta y_{i}}=2 \sum \limits _{j}\left(p_{j \mid i}-q_{j \mid i}+p_{i \mid j}-q_{i \mid j}\right)\left(y_{i}-y_{j}\right)$

  • Crowing 问题。即不同类别的簇挤在一起,无法区分开来。拥挤问题与某个特定算法无关,而是由于高维空间距离分布和低维空间距离分布的差异造成的。如高维度数据在降维到 10 维,可以有很好的表达,但降维到 2 维后无法得到可信映射。假设一个以数据点 $x_i$ 为中心,半径为 $r$ 的 $m$ 维球(三维空间就是球),其体积是按 $r^m$ 增长的,假设数据点是在 $m$ 维球中均匀分布的,我们来看看其他数据点与 $x_i$ 的距离随维度增大而产生的变化。

      

  从上图可以看到,随着维度的增大,大部分数据点都聚集在 $m$ 维球的表面附近,与点 $x_i$ 的距离分布极不均衡。如果直接将这种距离关系保留到低维,就会出现拥挤问题。

import matplotlib.pyplot as plt
import numpy as np
from numpy.linalg import norm
npoints = 1000 # 抽取1000个m维球内均匀分布的点
plt.figure(figsize=(20, 4))
for i, m in enumerate((2, 3, 5, 8)):
# 这里模拟m维球中的均匀分布用到了拒绝采样,即先生成m维立方中的均匀分布,再剔除m维球外部的点
accepts = []
while len(accepts) < 1000:
points = np.random.rand(500, m)
accepts.extend([d for d in norm(points, axis=1) if d <= 1.0]) # 拒绝采样
accepts = accepts[:npoints]
ax = plt.subplot(1, 4, i+1)
ax.set_xlabel('distance') # x轴表示点到圆心的距离
if i == 0:
ax.set_ylabel('count') # y轴表示点的数量
ax.hist(accepts, bins=np.linspace(0., 1., 50), color='green')
ax.set_title('m={0}'.format(str(m)), loc='left')
plt.show()

3 t-SNE

3.1 对称 SNE

  在 SNE 中,高维空间中条件概率 $p_{j \mid i}$ 不等于 $p_{i \mid j}$,低维空间中 $q_{j \mid i}$ 不等于 $q_{i \mid j} $,于是提出对称 $\mathrm{SNE} $,采用联合概率分布代替原始的条件概率,使得 $p_{i j}=p_{j i}, \quad q_{i j}=q_{j i} $

  优化  $p_{i  \mid j }$  和  $q_{i \mid j} $ 的 KL 散度的一种替换思路是,使用联合概率分布来替换条件概率分布,即 $P$ 是高维空间里各个点的联合概率分布, $Q$ 是低维空间下,目标函数为:

    $C=K L(P \| Q)=\sum \limits_{i} \sum \limits _{j} p_{i, j} \log \frac{p_{i j}}{q_{i j}}$

  在高维空间中定义 $p_{i j} $:

    $p_{i j}=\frac{\exp \left(-\left\|x_{i}-x_{j}\right\|^{2} / 2 \sigma^{2}\right)}{\sum \limits_ {k \neq l} \exp \left(-\left\|x_{k}-x_{l}\right\|^{2} / 2 \sigma^{2}\right)}$

  在低维空间中定义 $ q_{i j} $ :

    $q_{i j}=\frac{\exp \left(-\left\|y_{i}-y_{j}\right\|^{2}\right)}{\sum_{k \neq l} \exp \left(-\left\|y_{k}-y_{l}\right\|^{2}\right)}$

  但在高维空间中这样定义会带来异常值的问题。假设点  $x_{i}$  是一个噪声点,那么  $\left\|x_{i}-x_{j}\right\|$  的平方会很大,那么对于所有的  $j$,$p_{i j}$  的值都会很小,导致在低维映射下的  $y_{i}$  对整个损失函数的影响很小,但对于异常值,我们需要得到一个更大的惩罚,于是对高维空间中的联合概率修正为:

    $p_{i j}=\frac{p_{i\mid j}+p_{p_{j \mid i}}}{2}$

  这样就避免了异常值的问题,此时的梯度变为:

    $\frac{\delta C}{\delta y_{i}}=4 \sum_{j}\left(p_{i j}-q_{i j}\right)\left(y_{i}-y_{j}\right)$

  但对称 SNE 的效果只是略微优于 SNE 的效果。

3.2 引入 t 分布

  $t$-分布(t-distribution)用于根据小样本来估计呈正态分布且方差未知的总体的均值。如果总体方差已知(例如在样本数量足够多时),则应该用正态分布来估计总体均值。

  $t$分布曲线形态与 $n$(确切地说与自由度df)大小有关。与标准正态分布曲线相比,自由度 df 越小,$t$ 分布曲线愈平坦,曲线中间愈低,曲线双侧尾部翘得愈高;自由度 df 愈大,$t$ 分布曲线愈接近正态分布曲线,当自由度 $df=∞$ 时,$t$分布曲线为标准正态分布曲线。

  假设 $X$ 服从标准正态分布 $N (0,1)$, $Y$ 服从 $ \chi^{2}(n) $分布, 那么  $Z=\frac{X}{\sqrt{Y / n}} $ 的分布称为自由度为  $n$  的分布,记为  $Z \sim t(n) $ 。

  分布密度函数 $f_{Z}(x)=\frac{\operatorname{Gam}\left(\frac{n+1}{2}\right)}{\sqrt{n \pi} \operatorname{Gam}\left(\frac{n}{2}\right)}\left(1+\frac{x^{2}}{n}\right)^{-\frac{n+1}{2}} $

  其中,$ \operatorname{Gam}(\mathrm{x}) $ 为伽马函数。

  对称 SNE 在高维度下另外一种减轻”拥挤问题”的方法:在高维空间下,使用高斯分布将距离转换为概率分布,在低维空间下,使用更加偏重长尾分布的方式来将距离转换为概率分布。

      

长尾分布

  长尾(The Long Tail)这一概念是由“连线”杂志主编克里斯·安德森(Chris Anderson)在2004年十月的“长尾” 一文中最早提出,用来描述诸如亚马逊和Netflix之类网站的商业和经济模式。

      

  如图所示,右边蓝色长长的部分便是长尾。

  举个例子:
  如手机市场,可能某果和某为手机近几年大受欢迎,销量占比极高,是手机市场上的主流商品,那就是左边的红色部分。而其他的各类手机就是上图中的右边蓝色部分。

  长尾效应:
  长尾效应就是蓝色面积大于红色面积,就是市场中那些小而散的个性化需求的总和也能产生极为惊人的利益。

  t 分布是一种长尾分布,在图左中可以看到,在没有异常点时,t 分布与高斯分布的拟合结果基本一致。在图右,出现了部分异常点,由于高斯分布的尾部较低,对异常点比较敏感,为了照顾这些异常点,高斯分布的拟合结果偏离了大多数样本所在位置,方差也较大。相比之下,t  分布的尾部较高,对异常点不敏感,保证了其鲁棒性,因此其拟合结果更为合理,较好的捕获了数据的整体特征。

  图中有高斯分布和  t 分布两条曲线,表示点之间的相似性与距离的关系,高斯分布对应高维空间,t  分布对应低维空间。那么对于高维空间中相距较近的点,为了满足  $p_{i j}=q_{i j}$, 低维空间中的距离需要稍小一点; 而对于高维空间中相距较远的点,为了满足  $p_{i j}=q_{i j} $, 低维空 间中的距离需要更远。便满足同一簇内的点(距离较近)聚合的更紧密,不同簇之间的点(距离较远)更加疏远。

      

  引入 t 分布之后,在低维空间中,用自由度为 1 的 t 分布重新定义 :

    $q_{i j}=\frac{\left(1+\left\|y_{i}-y_{j}\right\|^{2}\right)^{-1}}{\sum \limits _{k \neq l}\left(1+\left\|y_{i}-y_{j}\right\|^{2}\right)^{-1}}$

  然后与原始 SNE 一样,我们使用 K-L 散度定义目标函数进行优化,从而求解。至此,关于 t-SNE 算法的原理部分,我们就介绍完了。

3.3 t-SNE 算法过程

  • $Data: X=x_{1}, \ldots, x_{n}$
  • 计算 cost function 的参数: 困惑度 Perp
  • 优化参数:设置迭代次数 $ \mathrm{T}$ , 学习速率$ \eta$ ,动量 $ \alpha(t)$
  • 目标结果是低维数据表示 $ Y^{T}=y_{1}, \ldots, y_{n}$
  • 开始优化
    • 计算在给定 Perp下的条件概率 $ p_{j \mid i}$ (参见上面公式)
    • 令 $ p_{i j}=\frac{p_{j\left|i+p_{i}\right| j}}{2 n}$
    • 用 $ N\left(0,10^{-4} I\right)$ 随机初始化 $ \mathrm{Y}$
    • 迭代,从 $ \mathrm{t}=1$ 到 $ \mathrm{T}$, 做如下操作:结束
      • 计算低维度下的 $ q_{i j}$ (参见上面的公式)
      • 计算梯度(参见上面的公式)
      • 更新 $ Y^{t}=Y^{t-1}+\eta \frac{d C}{d Y}+\alpha(t)\left(Y^{t-1}-Y^{t-2}\right)$
    • 结束
  • 结束

3.4 优化小技巧

  • 提前压缩 (ear1y compression) : 开始初始化的时候,各个点要离得近一点。这样小的距离,方便各个聚类中心的移动。可以通过引入 $L2$ 正则项 (距离的平方和) 来实现。
  • 提前夸大(ear1y exaggeration):在开始优化阶段, $ p_{i j}$ 乘以一个大于 1 的数进行扩大, 来避免因为 $ q_{i j}$ 太小导致优化太慢的问题。比如前 50 次迭代, $ p_{i j} $ 乘以 4。

  优化的过程动态图如下:

            

3.5 缺点

  • 主要用于可视化,很难用于其他目的。比如测试集合降维,因为他没有显式的预估部分,不能在测试集合直接降维;比如降维到10维,因为 t 分布偏重长尾,1个自由度的t分布很难保存好局部特征,可能需要设置成更高的自由度。
  • t-SNE 倾向于保存局部特征,对于本征维数(intrinsic dimensionality)本身就很高的数据集,是不可能完整的映射到 2-3 维的空间
  • t-SNE 没有唯一最优解,且没有预估部分。如果想要做预估,可以考虑降维之后,再构建一个回归方程之类的模型去做。但是要注意,t-SNE中距离本身是没有意义,都是概率分布问题。
  • 训练太慢。

t-SNE 从入门到放弃的更多相关文章

  1. CYQ.Data 从入门到放弃ORM系列:开篇:自动化框架编程思维

    前言: 随着CYQ.Data 开始回归免费使用之后,发现用户的情绪越来越激动,为了保持这持续的激动性,让我有了开源的念头. 同时,由于框架经过这5-6年来的不断演进,以前发的早期教程已经太落后了,包括 ...

  2. [精品书单] C#/.NET 学习之路——从入门到放弃

    C#/.NET 学习之路--从入门到放弃 此系列只包含 C#/CLR 学习,不包含应用框架(ASP.NET , WPF , WCF 等)及架构设计学习书籍和资料. C# 入门 <C# 本质论&g ...

  3. OpenStack从入门到放弃

    OpenStack从入门到放弃 目录: 为何选择云计算/云计算之前遇到的问题 什么是云计算 云服务模式 云应用形式 传统应用与云感知应用 openstack及其相关组件介绍 flat/vlan/gre ...

  4. 绕过校园网的共享限制 win10搭建VPN服务器实现--从入门到放弃

    一.开篇立论= =.. 上次说到博主在电脑上搭建了代理服务器来绕过天翼客户端的共享限制,然而经过实际测试还不够完美,所以本着生命不息,折腾不止的精神,我又开始研究搭建vpn服务器= =... (上次的 ...

  5. 《区块链:从入门到放弃》之obc安装步骤

    obc安装步骤 朋友们可能会好奇,厨师不研究菜谱怎么改研究兵法了,哈哈,我原本是app出身,最近被安排去预研区块链和比特币技术,2个月下来,颇有斩获.期间得到IBM的CC同学指导我一步一步安装obc的 ...

  6. win10搭建代理服务器实现绕过校园网的共享限制--从入门到放弃

    博主所在学校特别坑爹,校园网被电信一家垄断了,而且最恶心的还是电信要求一条网线只能供一台电脑上网,不许接路由器共享网络= =- (还有电信2M价格是380+每年,20m是500每年,而且网速都很慢= ...

  7. WPF从入门到放弃系列第二章 XAML

    本文是作者学习WPF从入门到放弃过程中的一些总结,主要内容都是对学习过程中拜读的文章的整理归纳. 参考资料 XAML 概述 (WPF):https://msdn.microsoft.com/zh-cn ...

  8. Android -- 带你从源码角度领悟Dagger2入门到放弃

    1,以前的博客也写了两篇关于Dagger2,但是感觉自己使用的时候还是云里雾里的,更不谈各位来看博客的同学了,所以今天打算和大家再一次的入坑试试,最后一次了,保证最后一次了. 2,接入项目 在项目的G ...

  9. Android -- 带你从源码角度领悟Dagger2入门到放弃(二)

    1,接着我们上一篇继续介绍,在上一篇我们介绍了简单的@Inject和@Component的结合使用,现在我们继续以老师和学生的例子,我们知道学生上课的时候都会有书籍来辅助听课,先来看看我们之前的Stu ...

  10. 从入门到放弃,.net构建博客系统(二):依赖注入

    文章目录:<从入门到放弃,.net构建博客系统> 从入门到放弃,.net构建博客系统(一):系统构建 从入门到放弃,.net构建博客系统(二):依赖注入 上一篇中有讲到项目启动时会进行io ...

随机推荐

  1. 流的文件操作(File)

    一.流的分类: 1.流按照方向分类:分为输入流和输出流,流的操作是相对于内存而言. 输入流的定义:当我们从数据源中将数据读取到内存中就称为输入流,也叫读取流. 输出流的定义:当我们将内存中处理好的数据 ...

  2. 用代码调用Storyboard里面的viewController

    今天在帮助群里的一个朋友弄pop事件,在他那边,当前的viewcontroller,不能pop出去. 初步估计,他的ViewController层级多,他自己没有理清. 因为pushViewContr ...

  3. namespace使用总结

    1.防止引用文件中函数名相同,导致函数重定义错误: //test1.php <?php namespace foo; function func(){ echo "test1/func ...

  4. Linux 修改swap虚拟内存大小

          swap是内存的交换区:换句话说,如果内存不够用了,那么系统会在硬盘上存储一些内存中不常用的数据,之后将这部分数据在存储中析构掉:这样内存就又有剩余空间可以运行东东啦,这个过程也就是所谓的 ...

  5. 导入外部jar包的方法

    注:使用的编译平台为eclipse <算法>一书中需要引入外部jar包(algs4.jar),因此特地去学了下导入外部jar包的方法.步骤如下: 1.先将algs4.jar拷到j如下路径: ...

  6. QT5删除隐藏目录+隐藏文件

    1.功能需求 删除一个目录(包括目录本身),同时删除该目录中所有文件及目录(含隐藏的) 2.遇到的问题 qt5中已经有了递归删除目录的函数--->bool QDir::removeRecursi ...

  7. js 在遍历时只会显示最后一个遍历到的结果

    在做项目时遇到了一个关于遍历的问题, 前提是:在ul中有n个li每个li从后台获取的数据中有一个sign的字段,当sign等于0时(li未被点击过)li会显示一个红点,当sign不等于0时(li已被点 ...

  8. 52-python 画图二维

    Python--matplotlib绘图可视化知识点整理 1.折线图: import numpy as np import matplotlib.pyplot as plt from pylab im ...

  9. Nginx-配置一个简单的http虚拟服务

    配置文件内容如下: #user nobody; worker_processes 4; #工作进程的个数,可以配置多个,一般配置成CPU的核数 pid logs/nginx.pid; # 此文件用于记 ...

  10. 转:【专题五】TCP编程

    前言 前面专题的例子都是基于应用层上的HTTP协议的介绍, 现在本专题来介绍下传输层协议——TCP协议,主要介绍下TCP协议的工作过程和基于TCP协议的一个简单的通信程序,下面就开始本专题的正文了. ...