第53课:t-SNE 高维数据可视化
1. 学习目标
- 理解 t-SNE(t-分布随机近邻嵌入)算法的基本思想和核心步骤。
- 掌握使用 scikit-learn 库实现 t-SNE 降维与可视化的完整流程。
- 学会通过调整关键参数(如困惑度、学习率)来优化可视化效果。
- 能够分析 t-SNE 可视化结果,并正确解读其揭示的数据结构和潜在聚类。
2. 核心概念
t-SNE 是什么? 想象你有一幅无比复杂的星图,每个星星代表一个数据点,它们之间的距离蕴含着重要的信息(例如,它们属于同一个星系)。但直接看这个三维(甚至更高维)的星图非常困难。t-SNE 的目标就是将这张“高维星图”投影到一张 2D 的“纸”上,同时尽可能地保留“星系”内部星星的紧密关系和不同“星系”之间的相对位置。它特别擅长发现数据中的局部结构和聚类,是高维数据探索性分析的利器。
核心步骤(简化理解):
- 在高维空间中“建交”:对每一对数据点,计算它们成为“邻居”的概率。距离近的点,这个概率高;距离远的点,概率低。
- 在低维空间中“尝试重建”:在低维(如2D)空间中随机初始化对应的点,并为它们也定义一个类似的“邻居”概率分布(这里使用了尾部更重的t分布,以缓解“拥挤问题”)。
- “模仿”与优化:通过优化算法,不断调整低维点的位置,使得低维空间中的“邻居”概率分布尽可能地匹配高维空间中的概率分布。简单说,就是让低维图中的“局部关系”和原图中尽量一样。
关键参数 perplexity(困惑度):
这个参数可以理解为“每个点考虑多少个有效邻居”。它大致控制着局部邻域的大小。值太小,每个点自成一派,结果可能过于破碎;值太大,可能会将不同的聚类混合在一起。通常建议在 5 到 50 之间尝试。
3. 代码示例
以下代码演示如何对经典的鸢尾花(Iris)数据集进行 t-SNE 降维和可视化。该数据集有4个特征(花萼/花瓣的长度和宽度),属于高维数据。
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
import warnings
warnings.filterwarnings('ignore') # 忽略部分警告,保持输出整洁
# 1. 加载并准备数据
iris = datasets.load_iris()
X = iris.data
y = iris.target
target_names = iris.target_names
# 数据标准化:对t-SNE等距离敏感的算法很重要
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
print(f"原始数据形状: {X.shape}") # 输出: (150, 4)
print(f"类别标签: {target_names}") # 输出: ['setosa', 'versicolor', 'virginica']
# 2. 应用t-SNE降维到2维
# 初始化t-SNE模型
# n_components=2: 降到2维
# perplexity=30: 常用值,可根据效果调整
# learning_rate='auto': 让算法自动选择合适的学习率
# random_state=42: 保证结果可重现
tsne = TSNE(n_components=2, perplexity=30, learning_rate='auto', random_state=42)
# 执行降维,返回2维坐标
X_tsne = tsne.fit_transform(X_scaled)
print(f"降维后数据形状: {X_tsne.shape}") # 输出: (150, 2)
# 3. 可视化结果
plt.figure(figsize=(10, 8))
# 为每个类别定义颜色和标记
colors = ['navy', 'turquoise', 'darkorange']
markers = ['*', '^', 'o']
for color, i, target_name in zip(colors, [0, 1, 2], target_names):
# 绘制该类别的所有点
plt.scatter(X_tsne[y == i, 0], X_tsne[y == i, 1],
color=color, alpha=.8, lw=2,
marker=markers[i], label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('Iris Dataset t-SNE Visualization (Perplexity=30)')
plt.xlabel('t-SNE Component 1')
plt.ylabel('t-SNE Component 2')
plt.grid(True, alpha=0.3)
plt.show()
# 4. (进阶) 观察不同perplexity的影响
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
perplexities = [5, 30, 50]
for ax, perplexity in zip(axes, perplexities):
tsne = TSNE(n_components=2, perplexity=perplexity, learning_rate='auto', random_state=42)
X_tsne_temp = tsne.fit_transform(X_scaled)
ax.scatter(X_tsne_temp[:, 0], X_tsne_temp[:, 1], c=y, cmap=plt.cm.Set1, alpha=0.8)
ax.set_title(f't-SNE with Perplexity={perplexity}')
ax.set_xlabel('Component 1')
ax.set_ylabel('Component 2')
ax.grid(True, alpha=0.3)
plt.tight_layout()
plt.show()
4. 实践练习
练习1:基础应用
在 sklearn 的 load_digits 数据集(手写数字图像,64维)上应用 t-SNE,并将结果可视化。观察数字(0-9)在 t-SNE 图上的分布是否有聚集趋势。尝试设置 perplexity=30。
练习2:参数调优
对练习1中的 digits 数据集,分别使用 perplexity 为 5, 15, 40 进行 t-SNE 降维,绘制三个子图对比效果。哪个 perplexity 值能最好地区分不同的数字簇?请简述理由。
练习3:结果解读与对比
加载 sklearn.datasets.make_moons 生成的二维“双月”数据集(注意:它本身就是2维的,但我们可以先人为增加噪音维度)。使用 t-SNE 将其从添加噪音后的高维空间映射回2维。观察 t-SNE 是否能基本还原出两个半月形的结构。与 PCA(另一种降维方法)的结果进行对比(可选)。
5. 常见错误
- 忘记标准化数据:t-SNE 依赖于样本间的距离(欧氏距离)。如果特征尺度差异很大,数值大的特征会主导距离计算,导致结果失真。在应用 t-SNE 前,务必对数据进行标准化(StandardScaler)。
- 误解 t-SNE 结果的距离:t-SNE 图上的点间绝对距离不一定有意义,它主要保留的是点间的相对邻近关系。图中两个靠得很远的簇,在原始高维空间里未必非常远;反之亦然。不应根据 t-SNE 图上的距离进行定量分析。
- 过度依赖默认参数:
perplexity和learning_rate的选择对结果影响显著。不要只使用一次运行的结果,应多次尝试不同的参数,尤其是perplexity,来观察稳定且有意义的结构。 - 运行多次结果不同:由于优化过程的随机初始化,即使设置了
random_state,在不同的库版本或硬件上结果可能仍有细微差别。这是正常的。关键是观察整体的聚类结构和趋势是否一致。 - 在大型数据集上直接运行:t-SNE 的计算复杂度较高(O(N²)),在大数据集(如数万样本)上会非常慢。可以考虑先使用 PCA 进行预处理降维(如降到50维),再进行 t-SNE。
6. 小结
本节课我们学习了用于高维数据可视化的强大工具——t-SNE。关键要点包括:
- 核心目的:t-SNE 的核心是将高维数据点映射到低维(通常是2D)空间,同时尽可能保持点之间的局部邻域关系,非常适合探索数据中是否存在自然的聚类或流形结构。
- 工作原理:它通过匹配高维和低维空间中点对之间的概率分布(相似度)来实现降维,是一个迭代优化过程。
- 关键参数:
perplexity(困惑度)是最重要的参数,它隐含地定义了每个点的“邻居”数量,需要根据数据特性和可视化目标进行调整。 - 正确使用:t-SNE 是一个强大的探索性和可视化工具,而非定量分析工具。结果应谨慎解读,避免过度推断点间的绝对距离。
- 标准流程:加载数据 -> 标准化 -> 初始化并训练 TSNE 模型 -> 可视化二维投影结果 -> 分析与解释。
t-SNE 是理解复杂数据结构的绝佳起点。在下一课,我们将学习另一种更高效、且能保持更多全局结构的降维技术——UMAP。