适合人群:零基础小白 | 核心思想:用更少的数字描述同样的事物
如果你觉得"100 个特征太多了,能不能只保留最重要的几个?"——恭喜你,你已经在想降维了。
目录
1. 为什么需要降维?——维度灾难
1.1 什么是"维度"?
想象你要描述一个苹果:
- 只说颜色 → 1 维
- 说颜色 + 重量 → 2 维
- 说颜色 + 重量 + 甜度 + 大小 + 产地 + ... → 很多维
在机器学习中,每一个特征就是一个维度。一张 64×64 的灰度图片就有 4096 个维度!
1.2 维度灾难(Curse of Dimensionality)
维度越高,问题越大:
维度增加带来的问题
================================
维度数 │ 需要的数据量(指数增长!)
───────────┼──────────────────────────
1 维 │ ■■ (10 个点就够)
2 维 │ ■■■■■ (100 个点)
3 维 │ ■■■■■■■■■■■ (1000 个点)
10 维 │ ■■■■■■■■■■■■■■■... (100亿个点!)
数据量跟不上维度增长 → 模型学不好 → 过拟合!
三大问题:
- 数据稀疏:高维空间中数据点之间距离都差不多,"远近"变得没有意义
- 计算爆炸:特征越多,训练时间越长,内存消耗越大
- 过拟合:维度太高,模型容易"记住"噪声而非规律
1.3 降维能帮什么忙?
降维前:100 个特征 → 训练慢、容易过拟合、无法可视化
│
▼ (降维算法)
│
降维后:2~10 个特征 → 训练快、泛化好、可以画图看!
2. 降维的生活类比
2.1 PCA ≈ 影子投影
想象你手里拿着一个 3D 的铁丝模型(比如一只纸鹤),用手电筒从不同角度照它:
手电筒角度 1 手电筒角度 2
(信息多) (信息少)
☀ ☀
\ |
\ |
╱═══╲ ╱═══╲
╱ 纸鹤 ╲ ╱ 纸鹤 ╲
╱═══════╲ ╱═══════╲
\ |
\ |
════════════ ════════════
影子形状丰富 影子只是一条线
(保留了最多信息) (丢了太多信息)
PCA 做的事:找到那个"影子最丰富"的投影角度,让降维后保留尽量多的信息。
2.2 t-SNE ≈ 地图压缩
想象你有一张世界地图(高维数据),要把它压缩到一张名片大小(2维):
真实世界(高维) 名片地图(2维)
北京 ←近→ 天津 北京 · 天津 (近的还是近)
北京 ←远→ 纽约 北京 · · 纽约(远的还是远)
t-SNE 的目标:
"邻居关系"在压缩前后保持不变!
原来靠近的点,压缩后还是靠近
原来远离的点,压缩后还是远离
3. PCA 主成分分析
3.1 核心思想:一句话总结
找到数据变化最大的方向,沿着这些方向投影。
3.2 用人话解释方差、特征值、特征向量
方差 = 数据的"分散程度"
方差小(数据挤在一起): 方差大(数据很分散):
· · · · ·
· · · · · ·
· · · · ·
· ·
→ 包含的信息少 → 包含的信息多
PCA 的原则:保留方差大的方向,丢弃方差小的方向。
特征向量 = "最佳投影方向"
二维数据的 PCA 过程
y
│ · ·
│ · · · ← 数据呈椭圆形分布
│ · · · · ·
│ · · ·
│ ·
└──────────── x
第 1 步:找到数据最分散的方向
y
│ ╱ · · ← PC1(第一主成分方向)
│ ╱· · · 数据在这个方向最分散
│╱· · · · ·
│ · · ·╱
│ ·╱
└──────────── x
第 2 步:找到与 PC1 垂直的方向
y
│ ╱ · ·
│ ╱· ·│· ← PC2(第二主成分方向)
│╱· · ·│· · 与 PC1 垂直
│ · · │·╱ 数据在这个方向不太分散
│ ·╱│
└──────────── x
如果只保留 PC1 → 2D 降到 1D!
用人话来说:
- 特征向量(Eigenvector):就是上图中的箭头方向,告诉你"往哪个方向看"
- 特征值(Eigenvalue):就是那个方向上数据的分散程度,数值越大越重要
- 主成分(Principal Component):按特征值从大到小排列的特征向量
类比:考试成绩
假设有 5 门课的成绩:语文、数学、英语、物理、化学
PCA 可能发现:
PC1 = 0.5×数学 + 0.4×物理 + 0.3×化学 → "理科能力"
PC2 = 0.6×语文 + 0.5×英语 → "文科能力"
只用 2 个主成分就概括了 5 门课的信息!
3.3 PCA 的数学步骤(简化版)
┌─────────────────────────────────────────────┐
│ PCA 算法步骤 │
├─────────────────────────────────────────────┤
│ │
│ 1. 数据标准化(让每个特征均值为0) │
│ ↓ │
│ 2. 计算协方差矩阵(衡量特征间的关联) │
│ ↓ │
│ 3. 求协方差矩阵的特征值和特征向量 │
│ ↓ │
│ 4. 按特征值从大到小排序 │
│ ↓ │
│ 5. 选前 k 个特征向量组成投影矩阵 │
│ ↓ │
│ 6. 用投影矩阵将原始数据变换到新空间 │
│ │
└─────────────────────────────────────────────┘
3.4 方差解释比(Explained Variance Ratio)
方差解释比告诉你:每个主成分保留了多少信息。
方差解释比(碎石图 / Scree Plot)
方差解释比(%)
100│
90│ ██
80│ ██
70│ ██
60│ ██
50│ ██
40│ ██ ██
30│ ██ ██
20│ ██ ██ ██
10│ ██ ██ ██ ██ ██ ← "肘部"之后的成分
0│ ██ ██ ██ ██ ██ ██ ██ ██ ██ ██ 贡献很小,可以丢弃
└─────────────────────────────────
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10
累计方差解释比:
100│ ●──●──●──● ← 趋于平坦
90│ ●──●
80│ ●──●
70│ ●
60│ ●
50│ ●
40│ ●
30│ ●
20│ ●
10│●
0│
└─────────────────────────────────
PC1 PC2 PC3 PC4 PC5 PC6 PC7 PC8 PC9 PC10
经验法则:选择累计方差达到 85%~95% 时的主成分数量
3.5 如何选择主成分数量?
三种常用方法:
| 方法 | 做法 | 适合场景 |
|---|---|---|
| 碎石图法 | 看曲线"肘部"拐点 | 快速判断 |
| 累计方差阈值 | 选累计方差 ≥ 90% 的数量 | 通用 |
| 交叉验证 | 看下游模型表现 | 最严谨 |
3.6 Python 代码实战:PCA
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# ============ 第一步:加载数据 ============
iris = load_iris()
X = iris.data # 4个特征:花萼长/宽、花瓣长/宽
y = iris.target # 3种鸢尾花
print(f"原始数据形状: {X.shape}") # (150, 4) → 150个样本,4个特征
# ============ 第二步:标准化 ============
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# ============ 第三步:PCA 降维 ============
pca = PCA(n_components=2) # 降到2维
X_pca = pca.fit_transform(X_scaled)
print(f"降维后形状: {X_pca.shape}") # (150, 2) → 150个样本,2个特征
# ============ 第四步:查看方差解释比 ============
print(f"各主成分方差解释比: {pca.explained_variance_ratio_}")
print(f"累计方差解释比: {sum(pca.explained_variance_ratio_):.2%}")
# 通常能达到 ~95%,说明 2 个主成分就够了!
# ============ 第五步:可视化 ============
plt.figure(figsize=(8, 6))
colors = ['red', 'green', 'blue']
names = iris.target_names
for i, (color, name) in enumerate(zip(colors, names)):
mask = y == i
plt.scatter(X_pca[mask, 0], X_pca[mask, 1],
c=color, label=name, alpha=0.7)
plt.xlabel('第一主成分 (PC1)')
plt.ylabel('第二主成分 (PC2)')
plt.title('PCA 降维:鸢尾花数据集')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()
绘制碎石图
# ============ 碎石图代码 ============
pca_full = PCA() # 不指定 n_components,保留所有主成分
pca_full.fit(X_scaled)
plt.figure(figsize=(8, 4))
# 子图1:各成分方差比
plt.subplot(1, 2, 1)
plt.bar(range(1, 5), pca_full.explained_variance_ratio_, alpha=0.7)
plt.xlabel('主成分编号')
plt.ylabel('方差解释比')
plt.title('碎石图(Scree Plot)')
# 子图2:累计方差比
plt.subplot(1, 2, 2)
cumsum = np.cumsum(pca_full.explained_variance_ratio_)
plt.plot(range(1, 5), cumsum, 'bo-')
plt.axhline(y=0.9, color='r', linestyle='--', label='90% 阈值')
plt.xlabel('主成分数量')
plt.ylabel('累计方差解释比')
plt.title('累计方差解释比')
plt.legend()
plt.tight_layout()
plt.show()
3.7 PCA 的 3D 到 2D 投影可视化
3D 空间中的数据点 PCA 投影到 2D
z
│ · ·
│ ····· · ·
│ ······· · · · · ·
│ ····· → · · · · ·
│ · · · · ·
│ · ·
y ───┘
╱ PC1 ──────→
x │
↓ PC2
原始:3 个坐标描述 降维:2 个坐标描述
每个点 (x, y, z) 每个点 (pc1, pc2)
类比:把 3D 物体的影子投在最信息丰富的那面墙上
3.8 PCA 的优缺点
| 优点 | 缺点 |
|---|---|
| 速度快,可处理大数据集 | 只能发现线性关系 |
| 数学理论成熟 | 主成分难以解释含义 |
| 可用于预处理提速 | 对异常值敏感 |
| 降维同时去噪 | 可能丢失非线性结构 |
4. t-SNE 可视化利器
4.1 PCA 的局限
PCA 只能找"直线方向",如果数据的结构是弯曲的呢?
PCA 看不到的结构(瑞士卷 Swiss Roll)
真实结构(展开后): PCA 投影(压扁了):
A ─── B ─── C A · B
│ │ · ·
│ 瑞士卷 │ → C · D
│ │ · ·
D ─── E ─── F E · F
A和F在卷上其实很远 A和F被投影到很近的位置
但PCA把它们压到一起了! 结构被破坏了!
4.2 t-SNE 的核心思想
在高维空间中"亲近"的点,在低维空间中也要"亲近"。
t-SNE 的全称:t-distributed Stochastic Neighbor Embedding(t 分布随机邻居嵌入)
步骤(人话版)
┌──────────────────────────────────────────────┐
│ t-SNE 的工作流程 │
├──────────────────────────────────────────────┤
│ │
│ 1. 在高维空间中,计算每对点之间的"亲近程度" │
│ (用高斯分布转化为概率) │
│ → 近的点概率高,远的点概率低 │
│ ↓ │
│ 2. 在低维空间中,随机放置所有点 │
│ ↓ │
│ 3. 也计算低维中每对点的"亲近程度" │
│ (用 t 分布转化为概率) │
│ ↓ │
│ 4. 调整低维中点的位置,让两个空间的 │
│ "亲近程度分布"尽可能一致 │
│ (最小化 KL 散度) │
│ ↓ │
│ 5. 反复迭代,直到收敛 │
│ │
└──────────────────────────────────────────────┘
邻域保持的直觉
t-SNE 邻域保持示意图
高维空间: 低维空间(t-SNE 输出):
B B
│ │
A ── C E A ── C E
│ ╱ │ ╱
D F ─ G D F ─ G
A 的邻居是 B,C,D A 的邻居还是 B,C,D ✓
F 的邻居是 E,G F 的邻居还是 E,G ✓
A 和 F 很远 A 和 F 还是远 ✓
邻居关系被完美保留了!
4.3 为什么用 t 分布?
高斯分布 vs t 分布
概率密度
│
│ ╱╲ 高斯分布:尾巴薄
│ ╱ ╲ → 远处的点概率太低
│╱ ╲ → 低维中点容易挤在一起
└──────────── 距离
概率密度
│
│ ╱╲ t 分布:尾巴厚("胖尾")
│ ╱ ╲ → 远处的点还有一定概率
│╱ ╲___________ → 不同簇之间有更多空间
└──────────── 距离 → 可视化效果更好!
4.4 Perplexity(困惑度)参数
Perplexity 是 t-SNE 最重要的超参数,可以理解为**"每个点关注多少个邻居"**。
Perplexity 对结果的影响
Perplexity = 5 Perplexity = 30 Perplexity = 100
(关注很少邻居) (适中,常用默认值) (关注很多邻居)
·· ·· ·· ··· ··· ··········
·· ·· ·· ····· ····· ··········
····· ····· ··········
很多小碎片 清晰的簇结构 所有点混在一起
过度关注局部 局部+全局平衡 过度关注全局
建议:尝试 5~50 的范围,常用 30
数据量大时可以适当增大 perplexity
4.5 Python 代码实战:t-SNE
from sklearn.manifold import TSNE
from sklearn.datasets import load_digits
import matplotlib.pyplot as plt
# ============ 加载手写数字数据集 ============
digits = load_digits()
X = digits.data # (1797, 64) → 8x8的图片展平为64维
y = digits.target # 0-9 的标签
print(f"数据形状: {X.shape}") # 64维!无法直接可视化
# ============ t-SNE 降到 2 维 ============
tsne = TSNE(
n_components=2, # 降到2维
perplexity=30, # 困惑度,默认30
random_state=42, # 固定随机种子以便复现
n_iter=1000, # 迭代次数
learning_rate='auto'
)
X_tsne = tsne.fit_transform(X)
# ============ 可视化 ============
plt.figure(figsize=(10, 8))
scatter = plt.scatter(X_tsne[:, 0], X_tsne[:, 1],
c=y, cmap='tab10', alpha=0.6, s=10)
plt.colorbar(scatter, label='数字标签')
plt.title('t-SNE 可视化:手写数字数据集')
plt.xlabel('t-SNE 维度 1')
plt.ylabel('t-SNE 维度 2')
plt.show()
# 你会看到 0-9 各自聚成一团,效果非常惊艳!
尝试不同的 Perplexity
fig, axes = plt.subplots(1, 3, figsize=(18, 5))
for ax, perp in zip(axes, [5, 30, 100]):
tsne = TSNE(n_components=2, perplexity=perp, random_state=42)
X_embedded = tsne.fit_transform(X)
ax.scatter(X_embedded[:, 0], X_embedded[:, 1],
c=y, cmap='tab10', s=5, alpha=0.6)
ax.set_title(f'Perplexity = {perp}')
ax.set_xticks([])
ax.set_yticks([])
plt.suptitle('不同 Perplexity 下的 t-SNE 效果对比')
plt.tight_layout()
plt.show()
4.6 t-SNE 使用注意事项
⚠ t-SNE 的常见陷阱
═══════════════════════════════════════
1. 簇的大小不代表真实大小
→ t-SNE 会自动调整密度
2. 簇之间的距离不代表真实距离
→ 只有"谁和谁是邻居"是可信的
3. 每次运行结果可能不同
→ 设置 random_state 固定随机种子
4. 不能用于新数据的变换
→ 没有 transform() 方法!
→ 只能 fit_transform()
5. 速度慢
→ 大数据集先用 PCA 降到 50 维
→ 再用 t-SNE 降到 2 维
5. LDA 线性判别分析(简介)
5.1 LDA vs PCA
PCA:无监督降维 LDA:有监督降维
"不管标签,找最分散的方向" "看着标签,找最容易分开的方向"
· · ○ ○ · · ○ ○
· · · ○ ○ · · · ○ ○
· · ○ ○ · · ○ ○
PCA 投影方向: LDA 投影方向:
────────→ (最分散) ─────→ (最容易区分两类)
两种方向可能不同!
PCA 关注整体分散程度
LDA 关注类间分离程度
5.2 LDA 的核心思想
组间距离最大化,组内距离最小化。
LDA 的目标
类别 A 类别 B
····· ○○○○○
····· ○○○○○
←─ d1 ──→
组间距离大 ✓
·····内部紧凑 ✓ ○○○○○内部紧凑 ✓
5.3 Python 代码
from sklearn.discriminant_analysis import LinearDiscriminantAnalysis
# LDA 降维(注意:需要标签 y)
lda = LinearDiscriminantAnalysis(n_components=2)
X_lda = lda.fit_transform(X_scaled, y) # 注意这里传了 y!
# LDA 最多只能降到 (类别数 - 1) 维
# 比如 3 类数据,最多降到 2 维
6. UMAP 简介
UMAP(Uniform Manifold Approximation and Projection)是 t-SNE 的"进化版"。
6.1 UMAP vs t-SNE
| 特性 | t-SNE | UMAP |
|---|---|---|
| 速度 | 慢 | 快(快 10 倍以上) |
| 全局结构 | 保持较差 | 保持较好 |
| 可扩展性 | 万级数据 | 百万级数据 |
| 新数据变换 | 不支持 | 支持 transform() |
| 理论基础 | 概率分布 | 拓扑学 |
6.2 Python 代码
# 需要先安装:pip install umap-learn
import umap
reducer = umap.UMAP(
n_components=2,
n_neighbors=15, # 类似 perplexity
min_dist=0.1, # 控制点的紧密程度
random_state=42
)
X_umap = reducer.fit_transform(X)
# UMAP 支持 transform(),可以处理新数据!
# X_new_umap = reducer.transform(X_new)
7. 方法对比与选择指南
7.1 PCA vs t-SNE 效果对比
同一份数据(手写数字 0-9),两种方法的可视化效果:
PCA 结果: t-SNE 结果:
2 2 333
2 2 5 5 3 333
2 2 2 5 5 5 1 1 1 3 3 111
2 2 5 5 1 1 1 1 1 1 1
4 4 8 8 1 1 555 222 111
4 4 4 8 8 8 5 555 2 222
4 4 8 8 8 555 222 888
3 3 3 8 888
7 7 7 7 3 3 7777 888
7 7 7 3 3 7 777 444
7 7 7777 4 444
444
类别之间有重叠 类别被清晰分开
全局结构保留好 局部结构保留好
适合数据预处理 适合数据探索可视化
7.2 选择指南
你的目标是什么?
│
┌────────────┼────────────┐
▼ ▼ ▼
数据预处理 可视化探索 有监督分类
(给模型用) (给人看) (有标签)
│ │ │
▼ ▼ ▼
PCA 数据量大吗? LDA
│
┌────┴────┐
▼ ▼
>万条 <万条
│ │
▼ ▼
UMAP t-SNE
7.3 方法总结表
| 方法 | 类型 | 速度 | 保留结构 | 可用于新数据 | 典型用途 |
|---|---|---|---|---|---|
| PCA | 线性/无监督 | 很快 | 全局 | 是 | 预处理、去噪 |
| t-SNE | 非线性/无监督 | 慢 | 局部 | 否 | 可视化 |
| LDA | 线性/有监督 | 快 | 类间 | 是 | 分类预处理 |
| UMAP | 非线性/无监督 | 较快 | 全局+局部 | 是 | 可视化+预处理 |
8. 实战案例
8.1 案例一:人脸识别预处理(PCA 降维 = Eigenfaces)
from sklearn.datasets import fetch_lfw_people
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.metrics import classification_report
# ============ 加载人脸数据 ============
faces = fetch_lfw_people(min_faces_per_person=70, resize=0.4)
X = faces.data
y = faces.target
target_names = faces.target_names
print(f"图片数量: {X.shape[0]}")
print(f"每张图片的像素数(维度): {X.shape[1]}") # 可能是 1850 维!
# ============ PCA 降维 ============
# 1850 维 → 150 维(减少了 92% 的维度!)
pca = PCA(n_components=150, whiten=True, random_state=42)
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.25, random_state=42
)
X_train_pca = pca.fit_transform(X_train)
X_test_pca = pca.transform(X_test)
print(f"累计方差解释比: {sum(pca.explained_variance_ratio_):.2%}")
# 通常 150 个成分就能保留 ~90% 的信息
# ============ 用 SVM 分类 ============
clf = SVC(kernel='rbf', C=1000, gamma=0.005)
clf.fit(X_train_pca, y_train)
y_pred = clf.predict(X_test_pca)
print(classification_report(y_test, y_pred, target_names=target_names))
# 准确率通常能达到 80%+ ,而维度减少了 90%!
关键点:PCA 提取的前几个主成分被称为 Eigenfaces(特征脸),每个主成分长得像一张"幽灵脸",代表人脸的某种变化模式(如光照、表情、角度)。
8.2 案例二:基因表达数据可视化(t-SNE)
import numpy as np
from sklearn.manifold import TSNE
from sklearn.preprocessing import StandardScaler
import matplotlib.pyplot as plt
# ============ 模拟基因表达数据 ============
# 真实场景中:几千个基因(特征)× 几百个细胞(样本)
np.random.seed(42)
n_genes = 2000 # 2000 个基因
n_cells = 500 # 500 个细胞
# 模拟 3 种细胞类型
cell_type_A = np.random.randn(200, n_genes) + np.array([1]*500 + [0]*1500)
cell_type_B = np.random.randn(150, n_genes) + np.array([0]*500 + [1]*500 + [0]*1000)
cell_type_C = np.random.randn(150, n_genes) + np.array([0]*1000 + [1]*500 + [0]*500)
X = np.vstack([cell_type_A, cell_type_B, cell_type_C])
y = np.array([0]*200 + [1]*150 + [2]*150)
print(f"原始数据: {X.shape}") # (500, 2000) → 2000维!
# ============ 先 PCA 降到 50 维(加速) ============
from sklearn.decomposition import PCA
pca = PCA(n_components=50)
X_pca = pca.fit_transform(StandardScaler().fit_transform(X))
# ============ 再 t-SNE 降到 2 维(可视化) ============
tsne = TSNE(n_components=2, perplexity=30, random_state=42)
X_tsne = tsne.fit_transform(X_pca)
# ============ 可视化 ============
plt.figure(figsize=(8, 6))
cell_types = ['A 型细胞', 'B 型细胞', 'C 型细胞']
colors = ['#e74c3c', '#2ecc71', '#3498db']
for i in range(3):
mask = y == i
plt.scatter(X_tsne[mask, 0], X_tsne[mask, 1],
c=colors[i], label=cell_types[i], alpha=0.6, s=20)
plt.xlabel('t-SNE 1')
plt.ylabel('t-SNE 2')
plt.title('t-SNE 可视化:不同细胞类型的基因表达模式')
plt.legend()
plt.show()
# 2000 维的基因数据被映射到了 2D,
# 不同细胞类型形成了清晰的簇!
实际应用:在单细胞 RNA 测序(scRNA-seq)中,t-SNE/UMAP 是标准的可视化方法,帮助生物学家发现新的细胞类型。
8.3 案例三:图像压缩(PCA)
import numpy as np
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
# ============ 加载图片(这里用 sklearn 的人脸数据) ============
from sklearn.datasets import fetch_olivetti_faces
faces = fetch_olivetti_faces()
X = faces.data # (400, 4096) → 每张脸 64×64 = 4096 像素
# ============ 用不同数量的主成分重建图片 ============
n_components_list = [5, 20, 50, 100, 200]
fig, axes = plt.subplots(1, len(n_components_list) + 1, figsize=(16, 3))
# 原始图片
sample = X[0].reshape(64, 64)
axes[0].imshow(sample, cmap='gray')
axes[0].set_title(f'原图\n4096 维')
axes[0].axis('off')
for idx, n_comp in enumerate(n_components_list):
pca = PCA(n_components=n_comp)
X_compressed = pca.fit_transform(X)
X_reconstructed = pca.inverse_transform(X_compressed)
# 计算压缩率
ratio = n_comp / 4096 * 100
axes[idx + 1].imshow(X_reconstructed[0].reshape(64, 64), cmap='gray')
axes[idx + 1].set_title(f'{n_comp} 个主成分\n(保留 {ratio:.1f}%)')
axes[idx + 1].axis('off')
plt.suptitle('PCA 图像压缩:不同主成分数量下的重建效果')
plt.tight_layout()
plt.show()
# 结果你会发现:
# 50 个主成分(仅 1.2% 的维度)就能较好还原人脸!
PCA 图像压缩效果示意
原图 5个PC 20个PC 50个PC 200个PC
(4096维) (模糊) (轮廓清晰) (比较清楚) (几乎一样)
┌────┐ ┌────┐ ┌────┐ ┌────┐ ┌────┐
│☺ │ │▓▓ │ │☺ │ │☺ │ │☺ │
│ │ │▓▓▓ │ │ │ │ │ │ │
│ │ │▓▓ │ │ │ │ │ │ │
└────┘ └────┘ └────┘ └────┘ └────┘
压缩率: 99.9% 99.5% 98.8% 95.1%
质量: 很差 一般 较好 优秀
9. 总结
9.1 核心知识点回顾
降维算法知识地图
═══════════════════════════════════════════════
为什么降维?
└── 维度灾难:数据稀疏、计算慢、过拟合
线性方法
├── PCA(无监督)
│ ├── 找方差最大的方向投影
│ ├── 关键概念:特征值、特征向量、方差解释比
│ ├── 用碎石图选择主成分数量
│ └── 适合:预处理、去噪、图像压缩
│
└── LDA(有监督)
├── 最大化类间距离,最小化类内距离
└── 适合:分类任务的预处理
非线性方法
├── t-SNE
│ ├── 保持邻居关系的概率分布
│ ├── perplexity:控制关注的邻居数量
│ ├── 结果不可复现、不能变换新数据
│ └── 适合:高维数据的 2D/3D 可视化
│
└── UMAP
├── t-SNE 的改进版,更快、更好
├── 支持 transform() 变换新数据
└── 适合:大规模数据可视化 + 预处理
9.2 实用口诀
┌───────────────────────────────────────────┐
│ │
│ 降维口诀(小白版) │
│ │
│ 数据太多维度高,降维算法来帮忙 │
│ PCA 投影找方差,线性快速好预处理 │
│ t-SNE 邻居要保持,可视化效果最惊艳 │
│ UMAP 速度更加快,大数据集首选它 │
│ LDA 分类需标签,类间最远类内紧 │
│ │
│ 先问自己要干啥? │
│ 预处理选 PCA,看图用 t-SNE/UMAP │
│ 有标签就试 LDA,没标签就用 PCA │
│ │
└───────────────────────────────────────────┘
9.3 常见面试题
Q1:PCA 和 t-SNE 的核心区别?
PCA 是线性方法,最大化方差(全局结构);t-SNE 是非线性方法,保持邻居关系(局部结构)。
Q2:什么时候用 PCA,什么时候用 t-SNE?
需要降维后继续建模 → PCA;需要可视化高维数据 → t-SNE/UMAP。
Q3:PCA 之前需要标准化吗?
需要!如果特征量纲不同(如身高 cm 和体重 kg),不标准化会导致大量纲特征主导结果。
Q4:t-SNE 的 perplexity 怎么选?
一般 5~50,默认 30。数据量越大可以适当增大。建议多试几个值比较效果。
Q5:为什么 t-SNE 不能用于预处理?
因为 t-SNE 没有显式的变换公式,不能对新数据做 transform();而且它优化的是可视化效果而非保留最多信息。
下一篇预告:聚类算法(K-Means、DBSCAN)—— 让机器自动发现数据中的群组
本文适合初学者入门,如有疑问或建议,欢迎交流讨论!