当前位置: 首页 > news >正文

第11篇:降维算法:PCA、t-SNE、UMAP

摘要
本文系统讲解三大主流降维算法:PCA(主成分分析)、t-SNE(t-分布随机邻域嵌入)和UMAP(统一流形近似与投影)。从协方差矩阵、特征值分解到流形学习思想,结合Scikit-learn与Python代码,实现高维数据的可视化与特征压缩,并对比其在MNIST手写数字数据集上的表现,帮助学习者掌握“让数据变简单”的艺术。


一、为什么需要降维?

高维数据带来“维度灾难”(Curse of Dimensionality):

  • 计算成本高:距离计算、模型训练变慢
  • 可视化困难:人类无法理解>3维空间
  • 过拟合风险:特征过多,样本相对不足
  • 噪声干扰:无关特征影响模型性能

降维(Dimensionality Reduction)目标:

  • 保留关键信息的前提下,将数据从高维映射到低维(通常2D/3D)。

二、PCA:主成分分析(线性降维)

2.1 核心思想

寻找数据方差最大的方向(主成分),将数据投影到这些方向上。

  • 第1主成分:方差最大的方向
  • 第2主成分:与第1正交且方差次大的方向
  • ...

2.2 数学原理

  1. 中心化X ← X - mean(X)
  2. 计算协方差矩阵Σ = (1/(n-1)) XᵀX
  3. 特征值分解Σ = VΛVᵀ
    • V:特征向量矩阵(主成分方向)
    • Λ:特征值对角阵(对应方差大小)
  4. 投影Z = X V_kV_k为前k个最大特征值对应的特征向量

2.3 从零实现PCA

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_irisclass PCA:def __init__(self, n_components=2):self.n_components = n_componentsself.components_ = Noneself.mean_ = Noneself.explained_variance_ratio_ = Nonedef fit(self, X):# 1. 中心化self.mean_ = np.mean(X, axis=0)X_centered = X - self.mean_# 2. 协方差矩阵cov_matrix = np.cov(X_centered, rowvar=False)# 3. 特征值分解eigen_vals, eigen_vecs = np.linalg.eigh(cov_matrix)# 4. 按特征值降序排列idx = np.argsort(eigen_vals)[::-1]eigen_vals = eigen_vals[idx]eigen_vecs = eigen_vecs[:, idx]# 5. 选择前k个主成分self.components_ = eigen_vecs[:, :self.n_components]# 6. 解释方差比total_var = np.sum(eigen_vals)self.explained_variance_ratio_ = eigen_vals[:self.n_components] / total_varreturn selfdef transform(self, X):X_centered = X - self.mean_return np.dot(X_centered, self.components_)def fit_transform(self, X):return self.fit(X).transform(X)# 使用鸢尾花数据集(4维 → 2维)
iris = load_iris()
X, y = iris.data, iris.targetpca = PCA(n_components=2)
X_pca = pca.fit_transform(X)# 可视化
plt.figure(figsize=(10, 7))
scatter = plt.scatter(X_pca[:,0], X_pca[:,1], c=y, cmap='viridis', alpha=0.7)
plt.xlabel(f'第一主成分 (解释方差: {pca.explained_variance_ratio_[0]:.2%})')
plt.ylabel(f'第二主成分 (解释方差: {pca.explained_variance_ratio_[1]:.2%})')
plt.title('PCA 降维结果')
plt.colorbar(scatter, ticks=[0,1,2], label='类别')
plt.show()

✅ PCA保留了约95%的方差,类别清晰可分。


三、t-SNE:t-分布随机邻域嵌入(非线性降维)

3.1 核心思想

t-SNE专注于保留局部结构,即“相似的样本在低维空间中仍相近”。

3.2 算法步骤

  1. 高维空间:计算样本ij相似度(用高斯分布):

    p_{j|i} = exp(-||x_i - x_j||² / (2σ_i²)) / Σ_{k≠i} exp(-||x_i - x_k||² / (2σ_i²))
    

    σ_i困惑度(Perplexity)决定。

  2. 低维空间:定义样本ij的相似度(用t分布,自由度=1):

    q_{ij} = (1 + ||y_i - y_j||²)^{-1} / Σ_{k≠l} (1 + ||y_k - y_l||²)^{-1}
    
  3. 优化:最小化PQKL散度

    KL(P||Q) = Σ p_{ij} log(p_{ij}/q_{ij})
    

    使用梯度下降优化Y

3.3 关键参数

  • 困惑度(Perplexity):约等于“有效邻居数”,通常5-50。
  • 学习率(Learning Rate):梯度下降步长。
  • 迭代次数:通常1000+

3.4 Scikit-learn实战t-SNE

from sklearn.manifold import TSNE# 对鸢尾花数据降维
tsne = TSNE(n_components=2, perplexity=30, n_iter=1000, random_state=42)
X_tsne = tsne.fit_transform(X)plt.figure(figsize=(10, 7))
plt.scatter(X_tsne[:,0], X_tsne[:,1], c=y, cmap='plasma', alpha=0.7)
plt.title('t-SNE 降维结果')
plt.show()

✅ t-SNE能更好分离类别,但结果随机性强,每次运行略有不同。


四、UMAP:统一流形近似与投影

4.1 UMAP vs t-SNE

UMAP是t-SNE的现代替代品,具有:

  • 更快的速度:适合大数据集
  • 更好的全局结构保持
  • 可逆性(部分实现)
  • 支持新样本投影

4.2 核心思想

  1. 将数据视为拓扑空间中的点。
  2. 构建高维空间的模糊拓扑表示(基于最近邻)。
  3. 在低维空间寻找最相似的拓扑结构

4.3 Scikit-learn实战UMAP

# 需先安装: pip install umap-learn
import umapumap_reducer = umap.UMAP(n_components=2, n_neighbors=15, min_dist=0.1, random_state=42)
X_umap = umap_reducer.fit_transform(X)plt.figure(figsize=(10, 7))
plt.scatter(X_umap[:,0], X_umap[:,1], c=y, cmap='Set1', alpha=0.7)
plt.title('UMAP 降维结果')
plt.show()

✅ UMAP在保持局部结构的同时,全局布局更清晰。


五、实战:MNIST手写数字可视化(784维 → 2维)

from sklearn.datasets import fetch_openml
import time# 加载MNIST(仅取前1000个样本加速)
mnist = fetch_openml('mnist_784', version=1, as_frame=False)
X_mnist, y_mnist = mnist.data[:1000], mnist.target[:1000].astype(int)# 标准化
X_mnist = X_mnist / 255.0# 比较三种算法
methods = {'PCA': PCA(n_components=2),'t-SNE': TSNE(n_components=2, perplexity=30, n_iter=500, random_state=42),'UMAP': umap.UMAP(n_components=2, n_neighbors=15, min_dist=0.1, random_state=42)
}results = {}
for name, method in methods.items():start = time.time()X_reduced = method.fit_transform(X_mnist)end = time.time()results[name] = X_reducedprint(f"{name} 用时: {end-start:.2f}秒")# 绘制对比图
fig, axes = plt.subplots(1, 3, figsize=(18, 6))
for ax, (name, X_reduced) in zip(axes, results.items()):scatter = ax.scatter(X_reduced[:,0], X_reduced[:,1], c=y_mnist, cmap='tab10', s=5)ax.set_title(f'{name} (MNIST)')ax.axis('off')
plt.tight_layout()
plt.show()

结果分析:

  • PCA:速度快,但类别重叠严重,仅保留线性结构。
  • t-SNE:类别分离好,但运行慢,局部结构强。
  • UMAP:速度接近PCA,效果接近t-SNE,综合性能最佳

六、降维的应用场景

6.1 数据可视化

  • 将高维数据(如词向量、图像特征)投影到2D/3D便于观察。

6.2 特征工程

  • 作为预处理步骤,降低后续模型(如SVM、K-Means)的输入维度。

6.3 去噪

  • PCA可过滤掉方差小的“噪声”主成分。

6.4 加速计算

  • 减少特征数量,提升训练和推理速度。

七、如何选择降维算法?

场景推荐算法
快速线性降维PCA
小数据集,追求最佳可视化t-SNE
大数据集,兼顾速度与效果UMAP
需要可逆变换PCA
探索数据流形结构UMAP

📌 一般建议:先用PCA快速探索,再用UMAP或t-SNE精细可视化。


八、总结与学习建议

本文我们:

  • 掌握了PCA的数学原理(协方差、特征分解);
  • 理解了t-SNE的KL散度优化与困惑度;
  • 学习了UMAP的拓扑流形思想;
  • MNIST上对比了三种算法;
  • 了解了降维的多种应用场景。

📌 学习建议

  1. 理解“保留什么”:PCA保全局方差,t-SNE/UMAP保局部邻近。
  2. 注意参数调优:如t-SNE的perplexity,UMAP的n_neighbors
  3. 结果非绝对:降维是近似,不同运行可能有差异。
  4. 结合后续任务:降维后需评估对下游任务的影响。

九、下一篇文章预告

第12篇:神经网络基础:从感知机到多层感知机(MLP)
我们将进入深度学习领域,讲解:

  • 感知机(Perceptron)的数学模型与局限
  • 激活函数(Sigmoid, ReLU, Tanh)的作用
  • 前向传播反向传播(Backpropagation)算法
  • 梯度下降损失函数
  • 使用NumPy从零实现MLP
  • Scikit-learn的MLPClassifier实战

揭开深度学习的“基石”——神经网络的神秘面纱!


参考文献

  1. 周志华. 《机器学习》(“西瓜书”). 第10章(降维与度量学习)。
  2. Maaten, L. v. d. & Hinton, G. (2008). Visualizing Data using t-SNE. JMLR.
  3. McInnes, L. et al. (2018). UMAP: Uniform Manifold Approximation and Projection. JOSS.
  4. Scikit-learn降维文档: 2.5. Decomposing signals in components (matrix factorization problems) — scikit-learn 1.7.1 documentation
  5. UMAP官方文档: UMAP: Uniform Manifold Approximation and Projection for Dimension Reduction — umap 0.5.8 documentation

http://www.dtcms.com/a/371576.html

相关文章:

  • 【Leetcode100】算法模板之二叉树
  • 深入理解假设检验:从抛硬币到药物实验的全景讲解
  • JavaScript笔记之JS 和 HTML5 的关系
  • 第4篇 conda install pytorch==2.0.0报错
  • 基于Echarts+HTML5可视化数据大屏展示-学生综合成绩评价系统大屏
  • 探索OpenResty:高性能Web开发利器
  • Lua 核心知识点详解
  • 26考研——内存管理_内存管理策略(3)
  • MySQL索引和B+Tree的关系
  • 《云原生配置危机:从服务瘫痪到韧性重建的实战全解》
  • 论文阅读-SelectiveStereo
  • 架构思维:重温限流算法原理与实战
  • 【面试题】关于RAG的五道题
  • redis的数据类型:List
  • 【mysql】SQL自连接:什么时候需要,什么时候不需要?
  • Android网络之WIFI技术网络模型概述
  • 【Pandas】3.1-数据预处理:列的基本操作
  • 【数据结构】经典 Leetcode 题
  • vector的使用和模拟实现
  • 开发思路篇:转账接口设计
  • 20250907-03:LangChain的六大核心模块概览
  • Python-LLMChat
  • 【C++】C++入门—(下)
  • 大数据毕业设计选题推荐-基于大数据的国家基站整点数据分析系统-Hadoop-Spark-数据可视化-BigData
  • 如何编写ICT模拟功能测试
  • 【C++】类与对象(下)
  • 在Ubuntu中如何使用PM2来运行一个编译好的Vue项目
  • Mysql数据库——第一阶段
  • 10 qml教程-自定义属性
  • 万字详解网络编程之TCP/IP协议与UDP协议