困惑度越大,降维结果中保留的非局部信息就越多。
是的,我相信这是一个正确的直觉。我认为 t-SNE 中的困惑参数的方式是它设置每个点被吸引到的邻居的有效数量。在 t-SNE 优化中,所有点对都相互排斥,但只有少数点对感受到吸引力。
因此,如果您的困惑度非常小,那么感受到任何吸引力的配对将会减少,并且由此产生的嵌入将趋于“蓬松”:排斥力将占主导地位并将整个嵌入膨胀成气泡状的圆形。
另一方面,如果你的困惑很大,集群往往会缩小成更密集的结构。
这是一个非常简单的解释,我必须说我从未见过对这种现象进行良好的数学分析(我怀疑这样的分析会很重要),但我认为它大致正确。
在模拟中看到它是有启发性的。在这里,我生成了一个数据集,其中包含六个 10 维高斯球(),它们彼此相距很远——到目前为止,即使对于困惑度 100,所有吸引力都在集群内。因此,对于 5 到 100 之间的困惑,如下所示,集群之间永远不存在任何吸引力。然而,人们可以清楚地看到,当困惑度增加时,集群会“缩小”。n=1000
事实上,一个人可以完全摆脱困惑,让每个点都对其最近的个邻居感到同样强烈的吸引力。这意味着我将高维空间中的高斯核替换为最近个邻居上的“均匀”核。这应该可以简化任何数学分析,并且可以说更直观。人们经常惊讶地发现,结果通常看起来与真实的 t-SNE非常相似。这是的各种值:KKK
代码
%matplotlib notebook
import numpy as np
import pylab as plt
import seaborn as sns
sns.set_style('ticks')
# https://github.com/KlugerLab/FIt-SNE
import sys; sys.path.append('/home/localadmin/github/FIt-SNE')
from fast_tsne import fast_tsne
col = np.array(['#a6cee3','#1f78b4','#b2df8a','#33a02c','#fb9a99',
'#e31a1c','#fdbf6f','#ff7f00','#cab2d6','#6a3d9a'])
n = 1000 # sample size per class
p = 10 # dimensionality
k = 6 # number of classes
d = 10 # distance between each class mean and 0
np.random.seed(42)
X = np.random.randn(k*n, p)
for i in range(k):
X[i*n:(i+1)*n, i] += d
perpl = [5, 30, 100]
Z1 = []
for p in perpl:
Z = fast_tsne(X, perplexity=p, seed=42)
Z1.append(Z)
ks = [5, 30, 100]
Z2 = []
for kk in ks:
Z = fast_tsne(X, K=kk, sigma=10000, seed=42)
Z2.append(Z)
fig = plt.figure(figsize=(7, 3))
for i,Z in enumerate(Z1):
plt.subplot(1,3,i+1)
plt.axis('equal', adjustable='box')
plt.scatter(Z[:,0], Z[:,1], s=1, c=col[np.floor(np.arange(n*k)/n).astype(int)])
plt.title('Perplexity {}'.format(perpl[i]))
plt.gca().get_xaxis().set_visible(False)
plt.gca().get_yaxis().set_visible(False)
sns.despine(left=True, bottom=True)
plt.tight_layout()
fig = plt.figure(figsize=(7, 3))
for i,Z in enumerate(Z2):
plt.subplot(1,3,i+1)
plt.axis('equal', adjustable='box')
plt.scatter(Z[:,0], Z[:,1], s=1, c=col[np.floor(np.arange(n*k)/n).astype(int)])
plt.title('K = {}'.format(perpl[i]))
plt.gca().get_xaxis().set_visible(False)
plt.gca().get_yaxis().set_visible(False)
sns.despine(left=True, bottom=True)
plt.tight_layout()