背景
t-SNE(t-Distributed Stochastic Neighbor Embedding)是一种非常流行的非线性降维技术,主要用来对高维数据进行可视化,了解和验证数据或者模型。t-SNE属于流行学习(manifold learning),假设数据是均匀采样于一个高维欧氏空间中的低维流形,流形学习就是从高维采样数据中恢复低维流形结构,即找到高维空间中的低维流形,并求出相应的嵌入映射,以实现维数约简或者数据可视化。
t-SNE 基本理论
假设一个数据集
X
X
X
,数据集中每个样本都是
D
D
D
维的,
X
∈
R
D
X\in R^D
X
∈
R
D
,t-SNE的目的是生成一个低维的特征集
Y
∈
R
d
Y\in R^d
Y
∈
R
d
来表征样本,其中
d
<
<
D
d<<D
d
<
<
D
。最典型的为
d
=
2
d=2
d
=
2
,从而将高维样本数据在二维平面上表示,方便观察数据的分布特性。
在降维过程中,目的是使原始空间中的两个样本点
x
i
x_i
x
i
和
x
j
x_j
x
j
在降维后的空间中对应的点
y
i
y_i
y
i
和
y
j
y_j
y
j
保持同样的距离分布。为了达到这样的效果,t-SNE将原始空间的相似性建模为概率密度,并且相似性的分布由高斯分布给出。即,在原始空间中已知样本点
i
i
i
的情况下,
j
j
j
点和
i
i
i
点间的相似性可以用条件概率分布公式来表示:
p
j
∣
i
=
exp
(
−
∥
x
i
−
x
j
∥
2
/
2
σ
i
2
)
∑
k
≠
i
exp
(
−
∥
x
i
−
x
k
∥
2
/
2
σ
i
2
)
p_{j | i}=\frac{\exp \left(-\|\mathbf{x}_i-\mathbf{x}_j\|^{2} / 2 \sigma_{i}^{2}\right)}{\sum_{k \neq i} \exp \left(-\|\mathbf{x}_i-\mathbf{x}_k\|^{2} / 2 \sigma_{i}^{2}\right)}
p
j
∣
i
=
∑
k
=
i
exp
(
−
∥
x
i
−
x
k
∥
2
/
2
σ
i
2
)
exp
(
−
∥
x
i
−
x
j
∥
2
/
2
σ
i
2
)
由于相似度是对称的,即
i
i
i
和
j
j
j
的相似度应该是等于
j
j
j
和
i
i
i
的相似度,所以最终的联合概率分布:
p
i
j
=
p
j
∣
i
+
p
i
∣
j
2
p_{i j}=\frac{p_{j | i}+p_{i | j}}{2}
p
i
j
=
2
p
j
∣
i
+
p
i
∣
j
在降维后的空间中,用学生t分布(Student’s t-distribution)代替高斯分布,因为学生t分布有更粗的尾巴,能够保留更多较远的距离的相似度。所以在降维后的目标空间中,联合概率分布为如下形式:
q
i
j
=
(
1
+
∥
y
i
−
y
j
∥
2
)
−
1
∑
k
≠
l
(
1
+
∥
y
k
−
y
l
∥
2
)
−
1
q_{i j}=\frac{\left(1+\|\mathbf{y}_i-\mathbf{y}_j\|^{2}\right)^{-1}}{\sum_{k \neq l}\left(1+\|\mathbf{y}_k-\mathbf{y}_l\|^{2}\right)^{-1}}
q
i
j
=
∑
k
=
l
(
1
+
∥
y
k
−
y
l
∥
2
)
−
1
(
1
+
∥
y
i
−
y
j
∥
2
)
−
1
目的是为了让这个两个概率分布尽可能的相似,这样就说明在降维后的数据分布和原始空间的数据分布基本一致,因此使用KL散度进行度量这两个分布之间的相似度:
C
=
K
L
(
P
∥
Q
)
=
∑
i
j
p
i
j
log
p
i
j
q
i
j
C=K L(\mathbf{P} \| \mathbf{Q})=\sum_{i j} p_{i j} \log \frac{p_{i j}}{q_{i j}}
C
=
K
L
(
P
∥
Q
)
=
i
j
∑
p
i
j
lo
g
q
i
j
p
i
j
根据以上目标函数进行优化,常用的优化方法就是梯度下降法。因为我们希望的是得到一个较好的
Y
Y
Y
,所以梯度如下:
∂
C
∂
y
i
=
4
∑
j
≠
i
(
p
i
j
−
q
i
j
)
(
y
i
−
y
j
)
(
1
+
∥
y
i
−
y
j
∥
2
)
−
1
\frac{\partial C}{\partial \mathbf{y} i}=4 \sum_{j \neq i}\left(p_{i j}-q_{i j}\right)(\mathbf{y}_i-\mathbf{y}_j)\left(1+\|\mathbf{y}_i-\mathbf{y}_j\|^{2}\right)^{-1}
∂
y
i
∂
C
=
4
j
=
i
∑
(
p
i
j
−
q
i
j
)
(
y
i
−
y
j
)
(
1
+
∥
y
i
−
y
j
∥
2
)
−
1
实例
手写数字可视化
# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
from sklearn import manifold,datasets
import time
import numpy as np
import matplotlib.pyplot as plt
# %%
n_components = 2
# %%
digits = datasets.load_digits(n_class=10)
data = digits['data']
label = digits['target']
n_samples, n_features = data.shape
n_features
# %%
tsne = manifold.TSNE(n_components=n_components, init='pca', random_state=0, perplexity=30)
start = time.time()
result = tsne.fit_transform(data)
end = time.time()
print('t-SNE time: {}'.format(end-start))
# %%
# result
# %%
x_min, x_max = np.min(result, 0), np.max(result, 0)
result = (result-x_min)/(x_max-x_min)
ax = plt.subplot(111)
for i in range(n_samples):
plt.text(result[i, 0], result[i, 1], str(label[i]), color=plt.cm.Set1(label[i] / 10.), fontdict={'weight': 'bold', 'size': 9})
plt.xticks([])
plt.yticks([])
plt.title('t-SNE-digits')
plt.show()