t-SNE完整笔记

http://www.datakit.cn/blog/2017/02/05/t_sne_full.htmlhtml

t-SNE(t-distributed stochastic neighbor embedding)是用于降维的一种机器学习算法,是由 Laurens van der Maaten 和 Geoffrey Hinton在08年提出来。此外,t-SNE 是一种非线性降维算法,很是适用于高维数据降维到2维或者3维,进行可视化。python

t-SNE是由SNE(Stochastic Neighbor Embedding, SNE; Hinton and Roweis, 2002)发展而来。咱们先介绍SNE的基本原理,以后再扩展到t-SNE。最后再看一下t-SNE的实现以及一些优化。web

目录

1.SNE

1.1基本原理

SNE是经过仿射(affinitie)变换将数据点映射到几率分布上,主要包括两个步骤:算法

  • SNE构建一个高维对象之间的几率分布,使得类似的对象有更高的几率被选择,而不类似的对象有较低的几率被选择。
  • SNE在低维空间里在构建这些点的几率分布,使得这两个几率分布之间尽量的类似。

咱们看到t-SNE模型是非监督的降维,他跟kmeans等不一样,他不能经过训练获得一些东西以后再用于其它数据(好比kmeans能够经过训练获得k个点,再用于其它数据集,而t-SNE只能单独的对数据作操做,也就是说他只有fit_transform,而没有fit操做)数据库

1.2 SNE原理推导

SNE是先将欧几里得距离转换为条件几率来表达点与点之间的类似度。具体来讲,给定一个N个高维的数据 x1,...,xNx1,...,xN(注意N不是维度), t-SNE首先是计算几率pijpij,正比于xixi和xjxj之间的类似度(这种几率是咱们自主构建的),即:express

pji=exp(∣∣xixj2/(2σ2i))kiexp(∣∣xixk2/(2σ2i))pj∣i=exp⁡(−∣∣xi−xj∣∣2/(2σi2))∑k≠iexp⁡(−∣∣xi−xk∣∣2/(2σi2))

这里的有一个参数是σiσi,对于不一样的点xixi取值不同,后续会讨论如何设置。此外设置pxx=0px∣x=0,由于咱们关注的是两两之间的类似度。数组

那对于低维度下的yiyi,咱们能够指定高斯分布为方差为12√12,所以它们之间的类似度以下:markdown

qji=exp(∣∣xixj2)kiexp(∣∣xixk2)qj∣i=exp⁡(−∣∣xi−xj∣∣2)∑k≠iexp⁡(−∣∣xi−xk∣∣2)

一样,设定qii=0qi∣i=0.网络

若是降维的效果比较好,局部特征保留完整,那么 pij=qijpi∣j=qi∣j, 所以咱们优化两个分布之间的距离-KL散度(Kullback-Leibler divergences),那么目标函数(cost function)以下:app

C=iKL(Pi∣∣Qi)=ijpjilogpjiqjiC=∑iKL(Pi∣∣Qi)=∑i∑jpj∣ilog⁡pj∣iqj∣i

这里的PiPi表示了给定点xixi下,其余全部数据点的条件几率分布。须要注意的是KL散度具备不对称性,在低维映射中不一样的距离对应的惩罚权重是不一样的,具体来讲:距离较远的两个点来表达距离较近的两个点会产生更大的cost,相反,用较近的两个点来表达较远的两个点产生的cost相对较小(注意:相似于回归容易受异常值影响,但效果相反)。即用较小的 qji=0.2qj∣i=0.2 来建模较大的 pji=0.8pj∣i=0.8, cost=plog(pq)plog⁡(pq)=1.11,一样用较大的qji=0.8qj∣i=0.8来建模较大的pji=0.2pj∣i=0.2, cost=-0.277, 所以,SNE会倾向于保留数据中的局部特征

思考:了解了基本思路以后,你会怎么选择σσ,固定初始化?

下面咱们开始正式的推导SNE。首先不一样的点具备不一样的σiσi,PiPi的熵(entropy)会随着σiσi的增长而增长。SNE使用困惑度(perplexity)的概念,用二分搜索的方式来寻找一个最佳的σσ。其中困惑度指:

Perp(Pi)=2H(Pi)Perp(Pi)=2H(Pi)

这里的H(Pi)H(Pi)是PiPi的熵,即:

H(Pi)=jpjilog2pjiH(Pi)=−∑jpj∣ilog2⁡pj∣i

困惑度能够解释为一个点附近的有效近邻点个数。SNE对困惑度的调整比较有鲁棒性,一般选择5-50之间,给定以后,使用二分搜索的方式寻找合适的σσ

那么核心问题是如何求解梯度了,目标函数等价于plog(q)∑∑−plog(q)这个式子与softmax很是的相似,咱们知道softmax的目标函数是ylogp∑−ylog⁡p,对应的梯度是ypy−p(注:这里的softmax中y表示label,p表示预估值)。 一样咱们能够推导SNE的目标函数中的i在j下的条件几率状况的梯度是2(pijqij)(yiyj)2(pi∣j−qi∣j)(yi−yj), 一样j在i下的条件几率的梯度是2(pjiqji)(yiyj)2(pj∣i−qj∣i)(yi−yj), 最后获得完整的梯度公式以下:

δCδyi=2j(pjiqji+pijqij)(yiyj)δCδyi=2∑j(pj∣i−qj∣i+pi∣j−qi∣j)(yi−yj)

在初始化中,能够用较小的σσ下的高斯分布来进行初始化。为了加速优化过程和避免陷入局部最优解,梯度中须要使用一个相对较大的动量(momentum)。即参数更新中除了当前的梯度,还要引入以前的梯度累加的指数衰减项,以下:

Y(t)=Y(t1)+ηδCδY+α(t)(Y(t1)Y(t2))Y(t)=Y(t−1)+ηδCδY+α(t)(Y(t−1)−Y(t−2))

这里的Y(t)Y(t)表示迭代t次的解,ηη表示学习速率,α(t)α(t)表示迭代t次的动量。

此外,在初始优化的阶段,每次迭代中能够引入一些高斯噪声,以后像模拟退火同样逐渐减少该噪声,能够用来避免陷入局部最优解。所以,SNE在选择高斯噪声,以及学习速率,何时开始衰减,动量选择等等超参数上,须要跑屡次优化才能够。

思考:SNE有哪些不足? 面对SNE的不足,你会作什么改进?

2.t-SNE

尽管SNE提供了很好的可视化方法,可是他很难优化,并且存在”crowding problem”(拥挤问题)。后续中,Hinton等人又提出了t-SNE的方法。与SNE不一样,主要以下:

  • 使用对称版的SNE,简化梯度公式
  • 低维空间下,使用t分布替代高斯分布表达两点之间的类似度

t-SNE在低维空间下使用更重长尾分布的t分布来避免crowding问题和优化问题。在这里,首先介绍一下对称版的SNE,以后介绍crowding问题,以后再介绍t-SNE。

2.1 Symmetric SNE

优化pijpi∣j和qijqi∣j的KL散度的一种替换思路是,使用联合几率分布来替换条件几率分布,即P是高维空间里各个点的联合几率分布,Q是低维空间下的,目标函数为:

C=KL(P∣∣Q)=ijpi,jlogpijqijC=KL(P∣∣Q)=∑i∑jpi,jlog⁡pijqij

这里的piipii,qiiqii为0,咱们将这种SNE称之为symmetric SNE(对称SNE),由于他假设了对于任意i,pij=pji,qij=qjipij=pji,qij=qji,所以几率分布能够改写为:

pij=exp(∣∣xixj2/2σ2)klexp(∣∣xkxl2/2σ2)    qij=exp(∣∣yiyj2)klexp(∣∣ykyl2)pij=exp⁡(−∣∣xi−xj∣∣2/2σ2)∑k≠lexp⁡(−∣∣xk−xl∣∣2/2σ2)    qij=exp⁡(−∣∣yi−yj∣∣2)∑k≠lexp⁡(−∣∣yk−yl∣∣2)

这种表达方式,使得总体简洁了不少。可是会引入异常值的问题。好比xixi是异常值,那么xixj2∣∣xi−xj∣∣2会很大,对应的全部的j, pijpij都会很小(以前是仅在xixi下很小),致使低维映射下的yiyi对cost影响很小。

思考: 对于异常值,你会作什么改进?pipi表示什么?

为了解决这个问题,咱们将联合几率分布定义修正为: pij=pij+pji2pij=pi∣j+pj∣i2, 这保证了jpij>12n∑jpij>12n, 使得每一个点对于cost都会有必定的贡献。对称SNE的最大优势是梯度计算变得简单了,以下:

δCδyi=4j(pijqij)(yiyj)δCδyi=4∑j(pij−qij)(yi−yj)

实验中,发现对称SNE可以产生和SNE同样好的结果,有时甚至略好一点。

2.2 Crowding问题

拥挤问题就是说各个簇汇集在一块儿,没法区分。好比有一种状况,高维度数据在降维到10维下,能够有很好的表达,可是降维到两维后没法获得可信映射,好比降维如10维中有11个点之间两两等距离的,在二维下就没法获得可信的映射结果(最多3个点)。 进一步的说明,假设一个以数据点xixi为中心,半径为r的m维球(三维空间就是球),其体积是按rmrm增加的,假设数据点是在m维球中均匀分布的,咱们来看看其余数据点与xixi的距离随维度增大而产生的变化。

show png

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

怎么解决crowding问题呢?

Cook et al.(2007) 提出一种slight repulsion的方式,在基线几率分布(uniform background)中引入一个较小的混合因子ρρ,这样qijqij就永远不会小于2ρn(n1)2ρn(n−1) (由于一共了n(n-1)个pairs),这样在高维空间中比较远的两个点之间的qijqij老是会比pijpij大一点。这种称之为UNI-SNE,效果一般比标准的SNE要好。优化UNI-SNE的方法是先让ρρ为0,使用标准的SNE优化,以后用模拟退火的方法的时候,再慢慢增长ρρ. 直接优化UNI-SNE是不行的(即一开始ρρ不为0),由于距离较远的两个点基本是同样的qijqij(等于基线分布), 即便pijpij很大,一些距离变化很难在qijqij中产生做用。也就是说优化中刚开始距离较远的两个聚类点,后续就没法再把他们拉近了。

2.3 t-SNE

对称SNE实际上在高维度下 另一种减轻”拥挤问题”的方法:在高维空间下,在高维空间下咱们使用高斯分布将距离转换为几率分布,在低维空间下,咱们使用更加偏重长尾分布的方式来将距离转换为几率分布,使得高维度下中低等的距离在映射后可以有一个较大的距离。

show png

咱们对比一下高斯分布和t分布(如上图,code见probability/distribution.md), t分布受异常值影响更小,拟合结果更为合理,较好的捕获了数据的总体特征。

使用了t分布以后的q变化,以下:

qij=(1+∣∣yiyj2)1kl(1+∣∣yiyj2)1qij=(1+∣∣yi−yj∣∣2)−1∑k≠l(1+∣∣yi−yj∣∣2)−1

此外,t分布是无限多个高斯分布的叠加,计算上不是指数的,会方便不少。优化的梯度以下:

δCδyi=4j(pijqij)(yiyj)(1+∣∣yiyj2)1δCδyi=4∑j(pij−qij)(yi−yj)(1+∣∣yi−yj∣∣2)−1

t-sne的有效性,也能够从上图中看到:横轴表示距离,纵轴表示类似度, 能够看到,对于较大类似度的点,t分布在低维空间中的距离须要稍小一点;而对于低类似度的点,t分布在低维空间中的距离须要更远。这刚好知足了咱们的需求,即同一簇内的点(距离较近)聚合的更紧密,不一样簇之间的点(距离较远)更加疏远。

总结一下,t-SNE的梯度更新有两大优点:

  • 对于不类似的点,用一个较小的距离会产生较大的梯度来让这些点排斥开来。
  • 这种排斥又不会无限大(梯度中分母),避免不类似的点距离太远。

2.4 算法过程

算法详细过程以下:

  • Data: X=x1,...,xnX=x1,...,xn
  • 计算cost function的参数:困惑度Perp
  • 优化参数: 设置迭代次数T, 学习速率ηη, 动量α(t)α(t)
  • 目标结果是低维数据表示 YT=y1,...,ynYT=y1,...,yn
  • 开始优化
    • 计算在给定Perp下的条件几率pjipj∣i(参见上面公式)
    • 令 pij=pji+pij2npij=pj∣i+pi∣j2n
    • 用 N(0,104I)N(0,10−4I) 随机初始化 Y
    • 迭代,从 t = 1 到 T, 作以下操做:
      • 计算低维度下的 qijqij(参见上面的公式)
      • 计算梯度(参见上面的公式)
      • 更新 Yt=Yt1+ηdCdY+α(t)(Yt1Yt2)Yt=Yt−1+ηdCdY+α(t)(Yt−1−Yt−2)
    • 结束
  • 结束

优化过程当中能够尝试的两个trick:

  • 提早压缩(early compression):开始初始化的时候,各个点要离得近一点。这样小的距离,方便各个聚类中心的移动。能够经过引入L2正则项(距离的平方和)来实现。
  • 提早夸大(early exaggeration):在开始优化阶段,pijpij乘以一个大于1的数进行扩大,来避免由于qijqij过小致使优化太慢的问题。好比前50次迭代,pijpij乘以4

优化的过程动态图以下:

optimise

2.5 不足

主要不足有四个:

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

3.变种

后续有机会补充。

  • multiple maps of t-SNE
  • parametric t-SNE
  • Visualizing Large-scale and High-dimensional Data

4.参考文档

  • Maaten, L., & Hinton, G. (2008). Visualizing data using t-SNE. Journal of Machine Learning Research.

5. 代码

文中的插图绘制:

# coding:utf-8 import numpy as np from numpy.linalg import norm from matplotlib import pyplot as plt plt.style.use('ggplot') def sne_crowding(): npoints = 1000 # 抽取1000个m维球内均匀分布的点 plt.figure(figsize=(20, 5)) 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) if i == 0: ax.set_ylabel('count') if i == 2: ax.set_xlabel('distance') ax.hist(accepts, bins=np.linspace(0., 1., 50)) ax.set_title('m=%s' %m) plt.savefig("./images/sne_crowding.png") x = np.linspace(0, 4, 100) ta = 1 / (1 + np.square(x)) tb = np.sum(ta) - 1 qa = np.exp(-np.square(x)) qb = np.sum(qa) - 1 def sne_norm_t_dist_cost(): plt.figure(figsize=(8, 5)) plt.plot(qa/qb, c="b", label="normal-dist") plt.plot(ta/tb, c="g", label="t-dist") plt.plot((0, 20), (0.025, 0.025), 'r--') plt.text(10, 0.022, r'$q_{ij}$') plt.text(20, 0.026, r'$p_{ij}$') plt.plot((0, 55), (0.005, 0.005), 'r--') plt.text(36, 0.003, r'$q_{ij}$') plt.text(55, 0.007, r'$p_{ij}$') plt.title("probability of distance") plt.xlabel("distance") plt.ylabel("probability") plt.legend() plt.savefig("./images/sne_norm_t_dist_cost.png") if __name__ == '__main__': sne_crowding() sne_norm_t_dist_cost() 

附录一下t-sne的完整代码实现:

# coding utf-8 ''' 代码参考了做者Laurens van der Maaten的开放出的t-sne代码, 并无用类进行实现,主要是优化了计算的实现 ''' import numpy as np def cal_pairwise_dist(x): '''计算pairwise 距离, x是matrix (a-b)^2 = a^w + b^2 - 2*a*b ''' sum_x = np.sum(np.square(x), 1) dist = np.add(np.add(-2 * np.dot(x, x.T), sum_x).T, sum_x) return dist def cal_perplexity(dist, idx=0, beta=1.0): '''计算perplexity, D是距离向量, idx指dist中本身与本身距离的位置,beta是高斯分布参数 这里的perp仅计算了熵,方便计算 ''' prob = np.exp(-dist * beta) # 设置自身prob为0 prob[idx] = 0 sum_prob = np.sum(prob) perp = np.log(sum_prob) + beta * np.sum(dist * prob) / sum_prob prob /= sum_prob return perp, prob def seach_prob(x, tol=1e-5, perplexity=30.0): '''二分搜索寻找beta,并计算pairwise的prob ''' # 初始化参数 print("Computing pairwise distances...") (n, d) = x.shape dist = cal_pairwise_dist(x) pair_prob = np.zeros((n, n)) beta = np.ones((n, 1)) # 取log,方便后续计算 base_perp = np.log(perplexity) for i in range(n): if i % 500 == 0: print("Computing pair_prob for point %s of %s ..." %(i,n)) betamin = -np.inf betamax = np.inf perp, this_prob = cal_perplexity(dist[i], i, beta[i]) # 二分搜索,寻找最佳sigma下的prob perp_diff = perp - base_perp tries = 0 while np.abs(perp_diff) > tol and tries < 50: if perp_diff > 0: betamin = beta[i].copy() if betamax == np.inf or betamax == -np.inf: beta[i] = beta[i] * 2 else: beta[i] = (beta[i] + betamax) / 2 else: betamax = beta[i].copy() if betamin == np.inf or betamin == -np.inf: beta[i] = beta[i] / 2 else: beta[i] = (beta[i] + betamin) / 2 # 更新perb,prob值 perp, this_prob = cal_perplexity(dist[i], i, beta[i]) perp_diff = perp - base_perp tries = tries + 1 # 记录prob值 pair_prob[i,] = this_prob print("Mean value of sigma: ", np.mean(np.sqrt(1 / beta))) return pair_prob def pca(x, no_dims = 50): ''' PCA算法 使用PCA先进行预降维 ''' print("Preprocessing the data using PCA...") (n, d) = x.shape x = x - np.tile(np.mean(x, 0), (n, 1)) l, M = np.linalg.eig(np.dot(x.T, x)) y = np.dot(x, M[:,0:no_dims]) return y def tsne(x, no_dims=2, initial_dims=50, perplexity=30.0, max_iter=1000): """Runs t-SNE on the dataset in the NxD array x to reduce its dimensionality to no_dims dimensions. The syntaxis of the function is Y = tsne.tsne(x, no_dims, perplexity), where x is an NxD NumPy array. """ # Check inputs if isinstance(no_dims, float): print("Error: array x should have type float.") return -1 if round(no_dims) != no_dims: print("Error: number of dimensions should be an integer.") return -1 # 初始化参数和变量 x = pca(x, initial_dims).real (n, d) = x.shape initial_momentum = 0.5 final_momentum = 0.8 eta = 500 min_gain = 0.01 y = np.random.randn(n, no_dims) dy = np.zeros((n, no_dims)) iy = np.zeros((n, no_dims)) gains = np.ones((n, no_dims)) # 对称化 P = seach_prob(x, 1e-5, perplexity) P = P + np.transpose(P) P = P / np.sum(P) # early exaggeration P = P * 4 P = np.maximum(P, 1e-12) # Run iterations for iter in range(max_iter): # Compute pairwise affinities sum_y = np.sum(np.square(y), 1) num = 1 / (1 + np.add(np.add(-2 * np.dot(y, y.T), sum_y).T, sum_y)) num[range(n), range(n)] = 0 Q = num / np.sum(num) Q = np.maximum(Q, 1e-12) # Compute gradient PQ = P - Q for i in range(n): dy[i,:] = np.sum(np.tile(PQ[:,i] * num[:,i], (no_dims, 1)).T * (y[i,:] - y), 0) # Perform the update if iter < 20: momentum = initial_momentum else: momentum = final_momentum gains = (gains + 0.2) * ((dy > 0) != (iy > 0)) + (gains * 0.8) * ((dy > 0) == (iy > 0)) gains[gains < min_gain] = min_gain iy = momentum * iy - eta * (gains * dy) y = y + iy y = y - np.tile(np.mean(y, 0), (n, 1)) # Compute current value of cost function if (iter + 1) % 100 == 0: if iter > 100: C = np.sum(P * np.log(P / Q)) else: C = np.sum( P/4 * np.log( P/4 / Q)) print("Iteration ", (iter + 1), ": error is ", C) # Stop lying about P-values if iter == 100: P = P / 4 print("finished training!") return y if __name__ == "__main__": # Run Y = tsne.tsne(X, no_dims, perplexity) to perform t-SNE on your dataset. X = np.loadtxt("mnist2500_X.txt") labels = np.loadtxt("mnist2500_labels.txt") Y = tsne(X, 2, 50, 20.0) from matplotlib import pyplot as plt plt.scatter(Y[:,0], Y[:,1], 20, labels) plt.show() 

 

 

 

https://yq.aliyun.com/articles/389822?utm_content=m_40767

 

假设你有一个包含数百个特征(变量)的数据集,却对数据所属的领域几乎没有什么了解。 你须要去识别数据中的隐藏模式,探索和分析数据集。不只如此,你还必须找出数据中是否存在模式--用以断定数据是有用信号仍是噪音?

这是否让你感到不知所措?当我第一次遇到这种状况,我简直全身发麻。想知道如何挖掘一个多维数据集? 这是许多数据科学家常常问的问题之一。 该篇文章中,我将带你经过一个强有力的方式来实现这一点。用PCA怎么样?

如今,必定会有不少人内心想着“我会使用PCA来降维和可视化”。 好吧,你是对的! PCA绝对是具备大量特征的数据集的降维和可视化的不错选择。 可是,假如你能使用比PCA更先进的东西将会怎样呢?

若是你能够很容易地找出非线性的模式呢? 在本文中,我将告诉你一个比PCA(1933)更有效、被称为t-SNE(2008)的新算法。 首先我会介绍t-SNE算法的基础知识,而后说明为何t-SNE是很是适合的降维算法。

你还将得到在R代码和Python语句中使用t-SNE的实践知识。

来吧来吧!

目录

1.什么是t-SNE?

2.什么是降维?

3.t-SNE与其余降维算法

4.t-SNE的算法细节

 4.1 算法

 4.2 时间和空间复杂性

5.t-SNE实际上作什么?

6.用例

7.t-SNE与其余降维算法相比

8.案例实践

 8.1 使用R代码

 

  • 超参数调试
  • 代码
  • 执行时间
  • 结果解读

 8.2 使用python语句

 

  • 超参数调试
  • 代码
  • 执行时间

9.什么时候何地去使用

 9.1 数据科学家

 9.2 机器学习竞赛爱好者

 9.3 数据科学爱好者

10.常见误区

1.什么是t-SNE

 

e8e556e681d7318d5bc3b82af54c9dfa58ac3a0c

(t-SNE)t-分布式随机邻域嵌入是一种用于挖掘高维数据的非线性降维算法。 它将多维数据映射到适合于人类观察的两个或多个维度。 在t-SNE算法的帮助下,你下一次使用高维数据时,可能就不须要绘制不少探索性数据分析图了。

 2.什么是降维?

为了理解t-SNE如何工做,让咱们先了解什么是降维?

简而言之,降维是在2维或3维中展示多维数据(具备多个特征的数据,且彼此具备相关性)的技术。

有些人可能会问,当咱们可使用散点图、直方图和盒图绘制数据,并用描述性统计搞清数据模式的时候为何还须要下降维度。

好吧,即便你能够理解数据中的模式并将其呈如今简单的图表上,可是对于没有统计背景的人来讲,仍然很难理解它。 此外,若是你有数百个特征值,你必须研究数千张图表,而后才能搞懂这些数据。

在降维算法的帮助下,您将可以清晰地表达数据。

3. t-SNE与其余降维算法

如今你已经了解什么是降维,让咱们看看咱们如何使用t-SNE算法来降维。

如下是几个你能够查找到的降维算法:

 

  1. 主成分分析(线性)
  2. t-SNE(非参数/非线性)
  3. 萨蒙映射(非线性)
  4. 等距映射(非线性)
  5. 局部线性嵌入(非线性)
  6. 规范相关分析(非线性)
  7. SNE(非线性)
  8. 最小方差无偏估计(非线性)
  9. 拉普拉斯特征图(非线性)

 

好消息是,你只须要学习上述算法中的其中两种,就能够有效地在较低维度上使数据可视化 - PCA和t-SNE。

PCA的局限性

PCA是一种线性算法。 它不能解释特征之间的复杂多项式关系。 另外一方面,t-SNE是基于在邻域图上随机游走的几率分布,能够在数据中找到其结构关系。

线性降维算法的一个主要问题是它们集中将不类似的数据点放置在较低维度区域时,数据点相距甚远。 可是为了在低维、非线性流型上表示高维数据,咱们也须要把类似的数据点靠近在一块儿展现,这并非线性降维算法所能作的。

如今,你对PCA应该有了一个简短的了解。

局部方法寻求将流型上的附近点映射到低维表示中的附近点。 另外一方面,全局方法试图保留全部尺度的几何形状,即将附近的点映射到附近的点,将远处的点映射到远处的点

要知道,除t-SNE以外的大多数非线性技术都不能同时保留数据的局部和全局结构。

4. t-SNE的算法细节(选读)

该部分是为有兴趣深刻理解算法的人准备的。 若是您不想了解数学上面的细节,能够放心地跳过本节。

 

4.1算法

步骤1

随机邻近嵌入(SNE)首先经过将数据点之间的高维欧几里得距离转换为表示类似性的条件几率。数据点gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA与数据点gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA的类似性是条件几率gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA——若是邻域被选择与在以gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA为中心的正态分布的几率密度成比例,gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA将选择gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA做为其邻域的几率。

ebb1c5edd82d15ed8526e870fa5d15cb9cc90352

其中640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=是以数据点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=为中心的正态分布的方差,若是你对数学不感兴趣,以这种方式思考它,算法开始于将点之间的最短距离(直线)转换成点的类似度的几率。 其中,点之间的类似性是: 若是在以640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=为中心的高斯(正态分布)下与邻域的几率密度成比例地选取邻域,则640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=会选择640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=做为其邻居的条件几率。

 

步骤2

对于低维数据点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=的高维对应点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=,能够计算相似的条件几率,其由640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=表示。

f5757ab6c47fa29665bb6e2230bca98696d60b91

须要注意的是,pi | i和pj | j被设置为零,由于咱们只想对成对的类似性进行建模。

简单来讲,步骤1和步骤2计算一对点之间的类似性的条件几率。这对点存在于:

 

  1. 高维空间中
  2. 低维空间中

 

为了简单起见,尝试详细了解这一点。

让咱们把3D空间映射到2D空间。 步骤1和步骤2正在作的是计算3D空间中的点的类似性的几率,并计算相应的2D空间中的点的类似性的几率。

逻辑上,条件几率640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=必须相等,以便把具备类似性的不一样维空间中的数据点进行完美表示。即,640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=之间的差必须为零,以便在高维和低维中完美复制图。

经过该逻辑,SNE试图使条件几率的这种差别最小化。

 

步骤3

如今讲讲SNE和t-SNE算法之间的区别。

为了测量条件几率SNE差值的总和的最小化,在全体数据点中使用梯度降低法使全部数据点的Kullback-Leibler散度总和减少到最小。 咱们必须知道,K-L散度本质上是不对称的。

换句话说,SNE代价函数重点在映射中保留数据的局部结构(为了高斯方差在高维空间的合理性,640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=)。

除此以外,优化该代价函数是很是困难的(计算效率低)。

所以,t-SNE也尝试最小化条件几率之差的总和值。 但它经过使用对称版本的SNE代价函数,使用简单的梯度。此外,t-SNE在低维空间中采用长尾分布,以减轻拥挤问题(参考下面译者解释)和SNE的优化问题。

*译者注:

拥挤问题是提出t-SNE算法的文章(Visualizing Data using t-SNE,08年发表在Journal of Machine Learning Research,大神Hinton的文章)重点讨论的问题(文章的3.2节)。译者的理解是,若是想象在一个三维的球里面有均匀分布的点,若是把这些点投影到一个二维的圆上必定会有不少点是重合的。因此在二维的圆上想尽量表达出三维里的点的信息,把因为投影所重合的点用不一样的距离(差异很小)表示,这样就会占用原来在那些距离上的点,原来那些点会被赶到更远一点的地方。t分布是长尾的,意味着距离更远的点依然能给出和高斯分布下距离小的点相同的几率值。从而达到高维空间和低维空间对应的点几率相同的目的。

步骤4

若是咱们看到计算条件几率的方程,咱们忽略了如今的讨论的方差。要选择的剩余参数是学生的t-分布的方差640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=,其中心在每一个高维数据点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=的中心。不可能存在对于数据集中的全部数据点最优的单个值640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=,由于数据的密度可能变化。在密集区域中,较小的值640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=一般与较稀疏的区域相比更合适。任何特定值640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=在全部其余数据点上诱发几率分布640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=。 这个分布有一个

c8212f64339ad90544fc67e5ddd00ea15b00c39c

该分布具备随着gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA增长而增长的熵。 t-SNE对gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA的值执行二进制搜索,产生具备由用户指定具备困惑度的gif;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAA2。 该困惑度定义为

45c9d6466a1c43e50e8a23013890f80ff728c240

其中H(640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=)是以比特字节测量的香农熵

4909e12dfd5d0cced685be93d24bb8c26fcc2be5

困惑度能够被解释为对邻域的有效数量的平滑测量。 SNE的性能对于茫然性的变化是至关稳固的,而且典型值在5和50之间。

代价函数的最小化是使用梯度降低法来执行的。而且从物理上,梯度能够被解释为由图上定位点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=和全部其余图上定位点640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=之间的一组弹簧产生的协力。全部弹簧沿着方向(640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy= - 640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=)施加力。弹簧在640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=定位点之间的排斥或吸引,取决于图中的两点之间的距离是太远仍是太近 (太远和太近都不能表示两个高维数据点之间的类似性。)由弹簧在640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=640?wx_fmt=png&tp=webp&wxfrom=5&wx_lazy=之间施加的力与其长度成比例,而且还与其刚度成比例,刚度是数据的成对类似性之间的失配(pj | i-qj | i + pi | j-qi | j) 点和地图点 。

 *译者补充:

步骤3和4都在讲述SNE 与t-SNE之间的区别,总结以下:

区别一:将不对称的代价函数改为对称的代价函数。

将代价函数修改成40804d1fe52bbef8eaa03c809d365d725fe148dd,其中9e13136309580387e3b636004af8730175b79451,则可避免上述不对称的代价函数所带来的问题。

区别二:在低维空间中使用学生t-分布而不是高斯分布来计算点与点之间的类似度。

t-SNE在低维空间中采用长尾的学生t-分布,02b033fab3fdb6fe5caf21c57f604c9cb74d92b5以减轻拥挤问题和SNE的优化问题。

4.2 时间和空间复杂度

如今咱们已经了解了算法,是分析其性能的时候了。 正如你可能已经观察到的,该算法计算成对的条件几率,并试图最小化较高和较低维度的几率差的总值。 这涉及大量的运算和计算。 因此该算法对系统资源至关重要。

t-SNE在数据点的数量上具备二次时间和空间复杂性。 这使得它应用于超过10,000个观察对象组成的数据集的时候特别慢和特别消耗资源。

 5. t-SNE 实际上作了什么?

了解了 t-SNE 算法的数学描述及其工做原理以后,让咱们总结一下前边学过的东西。如下即是t-SNE工做原理的简述。

实际上很简单。 非线性降维算法t-SNE经过基于具备多个特征的数据点的类似性识别观察到的模式来找到数据中的规律。它不是一个聚类算法,而是一个降维算法。这是由于当它把高维数据映射到低维空间时,原数据中的特征值不复存在。因此不能仅基于t-SNE的输出进行任何推断。所以,本质上它主要是一种数据探索和可视化技术。

可是t-SNE能够用于分类器和聚类中,用它来生成其余分类算法的输入特征值。

6. 应用场景

你可能会问, t-SNE有哪些应用场景呢?它几乎能够用于任何高维数据。不过大部分应用集中在图像处理,天然语言处理,基因数据以及语音处理。它还被用于提升心脑扫描图像的分析。如下维几个实例:

6.1 人脸识别

人脸识别技术已经取得巨大进展,不少诸如PCA之类的算法也已经在该领域被研究过。可是因为降维和分类的困难,人脸识别依然具备挑战性。t-SNE被用于高维度数据降维,而后用其它算法,例如 AdaBoostM2, 随机森林, 逻辑回归, 神经网络等多级分类器作表情分类。

一我的脸识别的研究采用了日本女性脸部表情数据库和t-SNE结合AdaBoostM2的方法。其实验结果代表这种新方法效果优于诸如PCA, LDA, LLE及SNE的传统算法。

如下为实现该方法的流程图: 

d40cdf28684eb888fc144953fb1a5f44d6a87292

6.2 识别肿瘤亚群(医学成像)

质谱成像(MSI)是一种同时提供组织中数百个生物分子的空间分布的技术。 t-SNE,经过数据的非线性可视化,可以更好地解析生物分子肿瘤内异质性。

以无偏见的方式,t-SNE能够揭示肿瘤亚群,它们与胃癌患者的存活和乳腺癌患者原发性肿瘤的转移状态具备统计相关性。 对每一个t-SNE簇进行的存活分析将提供很是有用的结果。[3] 

6.3 使用wordvec的文本比较

词向量表示法捕获许多语言属性,如性别,时态,复数甚至语义概念,如“首都城市”。 使用降维,能够计算出使语义类似的词彼此临近的2D地图。 这种技术组合能够用于提供不一样文本资料的鸟瞰图,包括文本摘要及其资料源。 这使用户可以像使用地图同样探索文本资料。[4]

 7. t-SNE与其它降维算法的对比

下边咱们将要比较t-SNE和其它算法的性能。这里的性能是基于算法所达到的准确度,而不是时间及运算资源的消耗与准确度之间的关系。

t-SNE产生的结果优于PCA和其它线性降维模型。这是由于诸如经典缩放的线性方法不利于建模曲面的流型。 它专一于保持远离的数据点之间的距离,而不是保留临近数据点之间的距离。

t-SNE在高维空间中采用的高斯核心函数定义了数据的局部和全局结构之间的软边界。对于高斯的标准误差而言彼此临近的数据点对,对它们的间隔建模的重要性几乎与那些间隔的大小无关。 此外,t-SNE基于数据的局部密度(经过强制每一个条件几率分布具备相同的困惑度)分别肯定每一个数据点的局部邻域大小[1]。 这是由于算法定义了数据的局部和全局结构之间的软边界。 与其余非线性降维算法不一样,它的性能优于其它任何一个算法。 

 8. 案例实践

让咱们用MNIST手写数字数据库来实现t-SNE算法。 这是最被普遍探索的图像处理的数据集之一。

81.使用R代码

“Rtsne”包具备t-SNE在R语言中的实现。“Rtsne”包能够经过在R控制台中键入如下命令安装:

 

 
  

 

 

  • 超参数调试

 

92778a3c0a11fef479bf88d754499d588e46adca

 

  • 代码

 

MNIST数据可从MNIST网站下载,并可用少许代码转换为csv文件。对于此示例,请下载如下通过预处理的MNIST数据。

 

 
  

 

 

  •  执行时间

 

 

 
  

 

能够看出,运行于相一样本规模的数据,与PCA相比t-SNE所需时间明显更长。

 

  • 解读结果

 

这些图可用于探索性分析。 输出的x和y坐标以及成本代价值能够用做分类算法中的特征值

988c96da554ec7785592e891a13df5af07604da1

8.2使用Rython语句

一个重要的事情要注意的是“pip install tsne”会产生错误。 不建议安装“tsne”包。 t-SNE算法能够从sklearn包中访问。

 

  • 超参数调试

 

68248d6912d110f229885e0aae66c8db4c17a567

 

  • 代码

 

如下代码引自sklearn网站的sklearn示例。

 

 
  

 

 

  • 执行时长

 

 

Tsne: 13.40 s
PCA: 0.01 s

 

PCA结果图(时长0.01s)

adf87ad6054d10442a04de9fe2410a2905fc4ef8

t-SNE结果图

d1c61095726880586731041ba09c8cb97a4d69f5

9.什么时候何地使用t-SNE?

9.1 数据科学家

对于数据科学家来讲,使用t-SNE的主要问题是算法的黑盒类型性质。这阻碍了基于结果提供推论和洞察的过程。此外,该算法的另外一个问题是它不必定在连续运行时永远产生相似的输出。

那么,你怎么能使用这个算法?最好的使用方法是用它进行探索性数据分析。 它会给你很是明确地展现数据内隐藏的模式。它也能够用做其余分类和聚类算法的输入参数。

9.2机器学习竞赛爱好者

将数据集减小到2或3个维度,并使用非线性堆栈器将其堆栈。 使用保留集进行堆叠/混合。 而后你可使用XGboost提升t-SNE向量以获得更好的结果。

9.3数据科学爱好者

对于才开始接触数据科学的数据科学爱好者来讲,这种算法在研究和性能加强方面提供了最好的机会。已经有一些研究论文尝试经过利用线性函数来提升算法的时间复杂度。可是还没有获得理想的解决方案。针对各类实施t-SNE算法解决天然语言处理问题和图像处理应用程序的研究论文是一个还没有开发的领域,而且有足够的空间范围。

10.常见错误

如下是在解释t-SNE的结果时要注意的几个点:

 

  1. 为了使算法正确执行,困惑度应小于数据点数。 此外,推荐的困惑度在(5至50)范围内
  2. 有时,具备相同超参数的屡次运行结果可能彼此不一样。
  3. 任何t-SNE图中的簇大小不得用于标准误差,色散或任何其余诸如此类的度量。这是由于t-SNE扩展更密集的集群,而且使分散的集群收缩到均匀的集群大小。 这是它产生清晰的地块的缘由之一。
  4. 簇之间的距离能够改变,由于全局几何与最佳困惑度密切相关。 在具备许多元素数量不等的簇的数据集中,同一个困惑度不能优化全部簇的距离。
  5. 模式也能够在随机噪声中找到,所以在决定数据中是否存在模式以前,必须检查具备不一样的超参数组的屡次运算结果。
  6. 在不一样的困惑度水平能够观察到不一样的簇形状。
  7. 拓扑不能基于单个t-SNE图来分析,在进行任何评估以前必须观察多个图。

 

参考资料

[1] L.J.P. van der Maaten and G.E. Hinton. Visualizing High-Dimensional Data Using  t-SNE. Journal of Machine Learning Research 9(Nov):2579-2605, 2008

[2] Jizheng Yi et.al. Facial expression recognition Based on t-SNE and AdaBoostM2.

IEEE International Conference on Green Computing and Communications and IEEE Internet of Things and IEEE Cyber,Physical and Social Computing (2013)

[3]  Walid M. Abdelmoulaa et.al. Data-driven identification of prognostic tumor subpopulations using spatially mapped t-SNE of mass spectrometry imaging data.

12244–12249 | PNAS | October 25, 2016 | vol. 113 | no. 43

[4]  Hendrik Heuer. Text comparison using word vector representations and dimensionality reduction. 8th EUR. CONF. ON PYTHON IN SCIENCE (EUROSCIPY 2015)

相关文章
相关标签/搜索