t-SNE 可视化:把高维数据看清楚

当你想把成百上千维的特征画成二维散点,t-SNE 是常见选择。它的目标很朴素:在原空间里相近的点,在二维图里也尽量相近。但”相近”在这里有严格数学定义,理解它,才不会把一张漂亮图误读成结论。

是什么

t-SNE(t-distributed Stochastic Neighbor Embedding)由 van der Maaten 与 Hinton 于 2008 年在 JMLR 提出。其核心思路是:把”点间距离”转成”相邻概率”——在高维用高斯分布描述点对彼此的相似度,在低维用重尾的 Student-t 分布描述;然后最小化两者差异(KL 散度)。

具体地说,对高维里每个点 i,按它与邻居 j 的距离算出条件概率 p_{j|i}(离得越近概率越大);低维里用 t 分布算出对应的 q_{j|i}。优化目标是让这两组概率分布尽可能一致,损失就是它们的 KL 散度。注意 p 是”条件”概率且经过对称化,它编码的是”邻域关系”而非”绝对距离”。

为什么低维用 t 分布?这是为了解决”拥挤问题”:把高维里分散的点压进二维时,可用空间急剧减少,点会互相挤成一团、难以分辨。Student-t 分布有重尾,能让中等距离的点在低维里被推得更开,从而缓解拥挤、让簇更清晰。

要点:
- 保留的是局部邻域结构,不是全局距离
- 用重尾的 t 分布缓解"拥挤问题"
- 结果是相对位置,不是真实度量,坐标本身无绝对意义

换句话说,t-SNE 学的是”谁和谁像邻居”,而不是”谁离谁多远”。

为什么有用

在特征工程与聚类探索中,t-SNE 能快速暴露数据中是否天然分群、是否存在异常离群点。相比 PCA 这类保全局方差的方法,它对局部流形结构更敏感,因此常用来”先看一眼”数据长什么样。但它是探索性工具,不是降维建模的终点——你不会拿它的坐标去做分类器输入,因为坐标间的数值关系不可信。

怎么用

以 scikit-learn 为例,TSNE 接受高维矩阵,输出二维或三维坐标。实务上建议先用 PCA 把维度压到约 50,再做 t-SNE——既提速(高维直接计算代价大),又滤掉噪声:

from sklearn.manifold import TSNE
from sklearn.decomposition import PCA
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt

digits = load_digits()
X = digits.data        # 1797 个样本 × 64 维
y = digits.target      # 真实标签,仅用于上色

X_pca = PCA(n_components=50, random_state=0).fit_transform(X)

tsne = TSNE(
    n_components=2,
    perplexity=30,        # 常用 5–50
    learning_rate='auto',
    init='pca',           # 用 PCA 初始化更稳
    n_iter=1000,
    random_state=0,
)
X_emb = tsne.fit_transform(X_pca)
print("KL 散度:", tsne.kl_divergence_)

# 按真实标签上色,便于直观看簇是否对应类别
plt.scatter(X_emb[:, 0], X_emb[:, 1], c=y, cmap="tab10", s=8)
plt.show()

几个关键参数:**困惑度(perplexity)**大致对应”每个点关注多少邻居”,常用 5 到 50。它平衡局部与全局:太小易碎成散点,太大各簇会糊在一起;经验上样本少则用较小困惑度。调参应看簇是否稳定,而非只图”好看”。learning_rate'auto' 通常即可;若手动设,过小会聚成团、过大点会散开。n_iter 建议不少于 750~1000 以防未收敛;init=‘pca’ 比随机初始化更稳、更少坏局部最优。生成的嵌入可用 joblib 持久化,避免重复训练。

注意点

最常见的误用有三类。其一,把图上的距离当真实相似度——t-SNE 不保全局距离,簇间距离没有意义,只有簇内紧凑度可参考。其二,跨运行比绝对坐标——每次随机初始化结果可能不同,应多跑几次看结构是否一致,而非对比具体坐标。其三,拿它做聚类唯一依据——它只是可视化,结论应回到原始特征或借助 KMeans、谱聚类等算法验证。

注意:
- 簇间距离无意义,别据此下结论
- 多次运行确认结构稳定,而非对齐坐标
- 高维先 PCA 再 t-SNE 更快更稳
- KL 散度只反映拟合程度,不代表"图好不好"
- 簇内距离同样不保真,别量像素下结论
- 离群点可能是真异常,也可能只是初始化产物

工程代价与替代:朴素实现随样本数平方增长,sklearn 默认用 Barnes-Hut 近似在样本较多时加速,但对上万样本仍可能较慢;此时可改看 UMAP——它在保留更多全局结构、速度上通常更有优势,API 用法与 t-SNE 类似,且支持 transform 对新数据映射(t-SNE 本身不提供稳定的 Out-of-sample 映射,新点需重新跑全量)。三类降维可作如是取舍:PCA 保全局方差、最快、可逆;t-SNE 保局部邻域、适合探索性看簇;UMAP 介于两者之间、速度更优且支持新样本。

小结

t-SNE 适合探索性地看簇结构,但不保全局距离。配合 PCA 预处理、合理选困惑度、多跑几次确认稳定,才能正确解读。记住:它回答”数据里有没有群”,不回答”群之间差多远”;用它发现结构,用更严谨的方法验证结构。

参考与延伸阅读

本文累计阅读