机器心脏排列
参与:蒋思远
介绍了T分布随机近邻嵌入算法,这是一种非常强大的高维数据降维方法。我们将首先介绍算法的基本概念和直观理解,然后详细分析和实现降维方法,最后介绍使用该算法的可视化结果。
t分布随机近邻嵌入是一种机器学习降维方法,可以帮助我们识别关联模式。t-SNE的主要优势是能够保持当地的结构。这意味着高维数据空中距离相似的点在低维上的投影仍然相似。SNE还能产生美丽的视觉效果。
构建预测模型时,第一步是了解数据。虽然搜索原始数据和计算一些基本的统计特征有助于理解,但没有什么比图表的可视化显示更直观的了。然而,将高维数据拟合到一个简单的图表(降维)是非常困难的,这就是t-SNE发挥作用的地方。
在本文中,我们将讨论t-SNE的原理以及t-SNE将如何帮助我们可视化数据。
SNE算法概念
本文主要介绍如何使用t-SNE进行可视化。虽然可以跳过这一章,生成漂亮的可视化,但还是需要讨论一下t-SNE算法的基本原理。
T-SNE算法对每个数据点的邻居分布进行建模,其中邻居是指彼此靠近的数据点的集合。在原高维空中,我们将高维空建模为高斯分布,而在二维输出空中,我们可以将其建模为T分布。这个过程的目标是找到从高维空到二维空的变换,并最小化这两个分布之间的差异。与高斯分布相比,T分布的尾部更长,有助于数据点在2D 空分布更均匀。
控制拟合的主要参数是虎符。混淆大致相当于匹配每个点的原始和拟合分布时考虑的最近邻。低混淆意味着我们在匹配原始分布和将每个数据点拟合到目标分布时只考虑最近邻,而高混淆意味着我们有更大的“全局观”。
因为分布是基于距离的,所以所有数据都必须是数字。我们应该通过二进制编码或者类似的方法将类别变量转化为数值变量,对数据进行归一化也是非常有效的,因为对数据进行归一化后,变量的取值范围不会相差太大。
t分布随机邻居嵌入算法(t-SNE)
Jake Hoare的博客并没有详细说明t-SNE的具体原理和推导过程,所以我们将在Geoffrey Hinton 2008年提出的论文以及liam schoneveld的推导和实现的基础上,详细介绍t-SNE算法。如果读者对这一章不感兴趣,也可以直接看下一章。杰克·霍尔在实践中使用t-SNE来可视化数据。
利亚姆·肖内费尔德推导和实现地址:https://nlml.github.io/in-raw-numpy/in-raw-numpy-t-sne/
地址:http://www . jmlr . org/papers/volume 9/vandermaten 08a/vandermaten 08a . pdf。
因为t-SNE是基于随机近邻嵌入的,所以我们首先需要了解随机近邻嵌入算法。
随机最近邻嵌入(SNE)
假设我们有一个数据集x,它有n个数据点。每个数据点x_i的维数是d,我们希望把它降维为d维。在可视化条件下,d的值为2,即所有数据都在平面上表示。
SNE通过将数据点之间的欧几里德距离转换成条件概率(以下用p_j|i表示)来表征相似性:
其中H(P_i)是P_i的香农熵,表示如下:
在SNE和t-SNE,混淆程度是我们设定的一个参数(通常在5到50之间)。我们可以为矩阵p的每一行设置一个σ_i,该行的混淆度等于我们设置的参数。直观来说,如果概率分布的熵大,则分布的形状相对平坦,分布中各元素的概率更接近。
混淆随着熵的增加而增加,所以如果我们想要有更高程度的混淆,那么所有的p_j|i(对于给定的I)将彼此更接近。换句话说,如果我们希望概率分布P_i更平坦,那么我们可以增加σ _ i,我们配置的σ_i越大,概率分布中所有元素的出现概率就越接近1/N。事实上,增加σ_i会增加每一点的邻居数,这就是为什么我们经常把混淆参数和我们需要的邻居数等同起来。
搜索σ_i
为了确保矩阵P的每一行的Perp(P_i)等于我们想要的值,我们可以简单地执行一个二分搜索法运算来确定σ_i可以得到我们想要的混淆。这个搜索很简单,因为Perp(P_i)是一个随σ _ i增大而增大的函数,下面是基本的二分搜索法函数:
defbinary_search(eval_fn,target,tol=1e-10,max_iter=10000,
下限=1e-20,上限=1000。):
" " "对eval_fn的输入值执行二分搜索法运算。
#参数
eval_fn:我们正在优化的功能。
目标:我们希望函数输出的目标值。
托尔:漂浮,一旦我们的猜测如此接近目标,停止。
max_iter:整数,最大数量。要搜索的迭代。
下限:浮动,搜索范围的下限。
上限:浮动,搜索范围的上限。
#返回:
浮点型,搜索过程中找到的函数的最佳输入值。
"""
fori inrange(max_iter):
guess =(低+高)/2。
val =eval_fn(猜测)
ifval >。目标:
上限=猜测
else:
低=猜测
ifnp.abs(val -target)<。=tol:
打破
返回猜测
要找到期望的σ_i,需要将eval_fn传递给binary_search函数,并以σ_i为其参数,返回p _ i的混淆度。
下面的find_optimal_sigmas函数正是这么做的,来搜索所有的σ_i,这个函数需要以负欧氏距离矩阵和目标混淆为输入。距离矩阵的每一行都将对所有可能的σ_i执行二进制搜索,以找到可能导致目标混淆的最佳σ。该函数最终将返回包含所有最优σ_i的NumPy向量..
defcalc _虎符(prob_matrix):
" " "算算每行的困惑
概率矩阵。"""
熵=-NP . sum(prob _ matrix * NP . log 2(prob _ matrix),1)
困惑= 2 * *熵
返回困惑
def困惑(距离,sigmas):
" " "用于快速计算的包装函数
距离矩阵的困惑。"""
returncalc _虎符(calc_prob_matrix(distances,sigmas))
deffind_optimal_sigmas(距离,目标_困惑):
" " "对于距离矩阵的每一行,找到产生的西格玛
在那个角色的目标困惑中。"""
sigmas =[]
#对于矩阵的每一行(数据集的每一点)
fori inrange(distances.shape[0]):
#使fn返回给定sigma的该行的困惑
eval_fn =lambdasigma:
困惑(距离[i:i+1,],np.array(sigma))
#二分搜索法战胜西格玛达到目标困惑
correct _ sigma = binary _ search(eval _ fn,target _虎符)
#将结果西格玛添加到我们的输出数组中
sigmas.append(correct_sigma)
returnnp . array(sigma)
对称SNE
现在估计SNE的所有条件都已经声明了,我们可以通过把代价C的梯度降低到Y来收敛到一个好的二维表示Y,因为SNE的梯度很难实现,所以我们可以用对称SNE,这是t-SNE论文中的一个替代方法。
在对称SNE中,我们最小化p_ij和q_ij的联合概率分布与p_i|j和q_i|j的条件概率之间的KL散度,并且我们将联合概率分布q_ij定义为:
该表达式就像我们前面定义的softmax函数一样,只是分母中的求和是在整个矩阵上执行的,而不是在当前行上。为了避免点X的异常值,我们简单地使p_ij = (p _ I | j+p _ j | i)/2n,而不是使p_ij服从相似分布。
我们可以简单地写出这些联合概率分布q和p:
defq_joint(Y):
" " "给定低维表示Y,计算
带有q_ij项的联合概率矩阵。"""
#获取每个点到其他点的距离
距离=负平方欧几里得距离(Y)
#取元素指数
exp_distances =np.exp(distances)
#用零填充对角线,因此q_ii = 0
np.fill _对角线(exp_distances,0。)
#除以整个指数矩阵的和
returnexp _ distances/NP . sum(exp _ distances),无
defp_conditional_to_joint(P):
" " "给定条件概率矩阵P,返回
联合分布概率的近似。"""
返回(P +P.T)/(2。*P形[0])
同样,我们可以定义p_joint函数的输入数据矩阵x,并返回联合概率p的矩阵,另外,我们还可以一起估计所需的σ_i和条件概率矩阵:
defp_joint(X,target _虎符):
" " "给定一个数据矩阵X,给出联合概率矩阵。
#参数
x:输入数据矩阵。
#返回:
p:条目p_ij =联合概率的矩阵。
"""
#获取我们数据的负欧几里德距离矩阵
距离=neg_squared_euc_dists(X)
#为距离矩阵的每一行找到最佳西格玛
sigmas =find_optimal_sigmas(距离,目标_困惑)
#根据这些最佳sigmas计算概率
p_conditional =calc_prob_matrix(距离,sigmas)
#从条件概率矩阵到联合概率矩阵
p = p _ conditional _ to _ joint(p _ conditional)
returnP
所以现在已经定义了联合概率分布p和q。如果我们计算这两个联合分布,我们可以用下面的梯度更新低维表示y的第I行:
在Python中,我们可以用下面的函数来估计梯度,即给定联合概率矩阵p和q以及当前的低维表示y来估计梯度:
defsymmetric_sne_grad(P,Q,Y,_):
"""估计成本相对于Y的梯度" " "
pq_diff =P -Q # NxN矩阵
pq _ expand = NP . expand _ dims(pq _ diff,2)#NxNx1
y_diffs =np.expand_dims(Y,1)-np.expand_dims(Y,0)#NxNx2
grad =4。*(pq _ expanded * y _ diff)。sum(1)#Nx2
returngrad
为了向量化变量,np.expand_dims方法将非常有用。这个函数返回的grad是N*2阶的矩阵,其中第I行是DC/dy _ i,一旦计算出梯度,就可以用它来进行梯度下降,也就是通过梯度下降迭代更新y _ i。
估计对称SNE
之前已经定义了估计对称SNE所需的所有函数,下面的训练函数将使用梯度下降算法迭代计算和更新权重。
defestimate_sne(X,y,P,rng,num_iters,q_fn,grad_fn,learning_rate,
动量,图):
" " "估计一个SNE模型。
#参数
x:输入数据矩阵。
y:该矩阵的类标签。
p:联合概率矩阵。
rng: np.random.RandomState()。
num_iters:要训练的迭代。
q_fn:取Y并给出Q prob矩阵的函数。
剧情:训练时要剧情多少次。
#返回:
y:矩阵,x的低维表示。
"""
#初始化我们的2D代表处
Y =rng.normal(0。,0.0001,[X.shape[0],2])
#初始化过去的值(用于动量)
if动量:
Y_m2 =Y.copy()
Y_m1 =Y.copy()
#开始梯度下降循环
fori inrange(num_iters):
#获取Q和距离(距离仅用于t-SNE)
q,距离=q_fn(Y)
#估计相对于Y的梯度
grads =grad_fn(P,Q,Y,距离)
#更新Y
Y = Y-学习_率*年级
如果动量:#增加动量
Y+=动量*(Y_m1 -Y_m2)
#更新前一个Y的动量
Y_m2 =Y_m1.copy()
Y_m1 =Y.copy()
#有时情节
if plot and I %(num _ iters/plot)= 0:
分类_分散_2d(Y,Y,α= 1.0,ms=6,
show=True,figsize=(9,6))
返回
为了简化表达式,我们将在MNIST数据集中使用标记为0、1和8的200个数据点,这是在main()函数中定义的:
#设置全局参数
点数=200#来自MNIST的样本数量
[0,1,8]#要使用的MNIST类
困惑=20
种子=1#随机种子
动量=0.9
LEARNING_RATE =10。
NUM_ITERS =500#要训练的迭代次数
TSNE =假#如果假,对称SNE
NUM_PLOTS =5# Num。训练中的绘图时间
defmain():
# numpy RandomState再现性
rng =np.random.RandomState(SEED)
#从MNIST加载第一个数字点0、1和8
x,y = load _ mnist(' dataset/',
数字_ to _ keep = CLASSES _ TO _ USE,
N = NUM _ POINTS)
#获取联合概率矩阵p_ij
P =p_joint(X,HOURENCE)
#适合SNE或SNE
y =估计_sne(X,y,P,rng,
num_iters=NUM_ITERS,
q _ fn = q _ tsne ifTSNE elseq _ joint,
grad _ fn = tsne _ grad if SNE else symmetric _ SNE _ grad,
learning_rate=LEARNING_RATE,
动量=动量,
plot=NUM_PLOTS)
建设SNE
我们已经分析了许多关于随机近邻嵌入的方法和概念,并推导出对称SNE,但幸运的是将对称SNE推广到t-SNE是非常简单的。真正的区别只是我们定义联合概率分布矩阵q的方式,在t-SNE中,我们定义q_ij的方法可以改变如下:
上面的公式是假设q_ij服从1自由度的Student分布推导出来的。范德马滕和辛顿注意到分布有一个很好的性质,就是计数器在低维空对于大距离有平方反比变化规律。本质上,这意味着该算法对于低维映射的一般尺度是不变的。因此,优化对于远点和近点都具有相同的执行模式。
这就解决了所谓的“拥塞问题”,即当我们试图将一个高维数据集刻画为二维或三维时,很难区分相邻的数据点和中等距离的数据点,因为这些数据点都聚集在一个区域内。
我们可以使用以下函数来计算新的q_ij:
defq_tsne(Y):
" " " SNE:给定低维表示Y,计算
带有q_ij项的联合概率矩阵。"""
距离=负平方欧几里得距离(Y)
inv_distances =np.power(1。-距离,-1)
np.fill _对角线(inv_distances,0。)
returninv_distances/NP . sum(inv _ distances),inv _ distances
请注意,我们使用1。-距离而不是1。+距离,距离函数将返回负距离。现在剩下的就是重新估计损失函数到y的梯度,梯度的表达式是从t-SNE论文中导出的,如下所示:
同样,我们可以根据计算对称SNE梯度的方法很容易地构造出t-SNE的梯度计算方法:
deftsne_grad(P,Q,Y,inv_distances):
"""估计t-SNE成本相对于y的梯度。" " "
pq _ diff = pq
pq _ expand = NP . expand _ dims(pq _ diff,2)
y_diffs =np.expand_dims(Y,1)-np.expand_dims(Y,0)
#扩展我们的inv_distances矩阵,以便可以乘以y _ diffs
distances _ expanded = NP . expand _ dims(inv _ distances,2)
#乘以距离矩阵的倒数
y _ diffs _ wt = y _ diffs * distances _ expanded
#乘上j,然后求和
grad =4。*(pq_expanded *y_diffs_wt)。总和(1)
returngrad
以上,我们已经完成了t-SNE的具体理解和实现,那么这个算法在具体数据集上的可视化效果如何呢?杰克·霍尔给出了可视化的效果和对比。
SNE可视化
接下来,我们将展示SNE可视化高维数据的结果。第一个数据集是根据物理特征分类的10片不同的叶子。在这种情况下,t-SNE需要使用14个数值变量作为输入,包括叶片生长率和长宽比。下图是二维可视化输出,植物的种类(标签)用不同的颜色表示。
掌叶槭的数据点在右上角形成一个橙色的簇,说明它的叶子与其他物种有很大的不同。在这个例子中,类别通常被很好地分组,并且相同物种的叶子(相同颜色的数据点)倾向于彼此靠近地聚集在一起。左下角两种颜色的数据点靠得很近,说明这两个物种的叶形很像。
最近邻精度表示两个随机点是同一物种的概率。如果将这些数据点按照不同的物种进行完美的分类,准确率会非常接近100%,高准确率意味着数据可以干净利落的划分成不同的聚类。
调整混乱
下面,我们对可口可乐品牌做了类似的分析。为了论证虎符的影响,我们首先需要将虎符设置为较低的值2,每个数据点的映射只考虑最近邻。如下,我们会看到很多离散的小簇,每个簇只有几个数据点。
让我们把t-SNE的混淆度设置为100,可以看到数据点变得更加分散,同一个类之间的联系变弱。
这种情况下可乐本身比叶子更难分。即使某个品牌的数据点比较集中,也还是没有明确的界限。
在实践中,混淆程度没有绝对的标准,但一般在5-50之间选择比较好。在这个范围内,t-SNE总体上是稳健的。
预测解释
测量数据点之间的角度或距离不能推断数据上的任何具体或定量信息,因此t-SNE预测更多地用于可视化数据。
在建模初期直观地挖掘数据模式,有助于指导数据科学的下一步进程。如果t-SNE能够很好地分割数据点,机器学习也可以找到一个很好的方法将未知的新数据投影到相应的类别中。给定一个预测算法,我们可以达到很高的精度。
在上面的例子中,每个类别都被隔离和分类,所以一个简单的机器学习模型可以将这个类别与其他类别分开。但是如果类别重叠,我们可能需要建立一个更复杂的模型来进行预测。如下图,如果按照一个品牌的喜好从1到5进行分类,类别可能会更加离散,难以预测,最近邻准确率会相对较低。
比较PCA
自然,我们想比较t-SNE和其他降维算法。主成分分析是一种流行的降维算法,主成分分析会寻找一个能尽可能保持数据方差的新维度。方差较大的数据会保留更多的信息,因为不同的数据可以提供不同的信息,所以我们最好将数据点彼此分开,因为它们提供了更大的方差。
以下是用PCA算法对上述叶类进行降维的结果。我们可以看到,虽然左边的橙色是分开的,但其他类别是混合在一起的。这是因为PCA不关心局部最近邻,而且PCA是线性方法,所以在刻画非线性关系时可能不太有效。然而,主成分分析算法在将数据压缩成更小的特征向量并将其应用于预测算法方面具有良好的性能,优于t-SNE算法。
标签
T-SNE算法是一种优秀的高维数据可视化算法,通常比其他降维算法产生更多的特征可视化结果。在数据分析中,获取数据的先验知识总是很重要的。正如华先生所说,当数字看不见时,就不那么直观,而当数字很小时,就很难做到细致入微。我们只能先了解数据的大致分布,然后选择具体的算法来进一步分析这些数据。数形结合各方面都不错,一切都免于分离。也许高维数据可视化和机器学习算法的结合才是打开数据分析的正确途径。
参考链接:
http://www . jmlr . org/papers/volume 9/vandermaten 08a/vandermaten 08a . pdf
https://www . displayr . com/using-t-SNE-to-visualize-data-before-prediction/
https://nlml.github.io/in-raw-numpy/in-raw-numpy-t-sne/
这篇文章是为机器的核心而写的。请联系本微信官方账号进行授权。
1.《tsne 深度 | 详解可视化利器t-SNE算法:数无形时少直觉》援引自互联网,旨在传递更多网络信息知识,仅代表作者本人观点,与本网站无关,侵删请联系页脚下方联系方式。
2.《tsne 深度 | 详解可视化利器t-SNE算法:数无形时少直觉》仅供读者参考,本网站未对该内容进行证实,对其原创性、真实性、完整性、及时性不作任何保证。
3.文章转载时请保留本站内容来源地址,https://www.lu-xu.com/keji/1613242.html