跳到主要内容

PCA 降维

主成分分析(PCA)是最经典的线性降维算法,将高维数据投影到低维空间,同时保留尽可能多的信息。

核心思想

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

  • 第一主成分:方差最大的方向
  • 第二主成分:与第一主成分正交的前提下,方差最大的方向
  • 依此类推...

数学推导

  1. 中心化数据(减均值)
  2. 计算协方差矩阵 C=1n1XTXC = \frac{1}{n-1} X^T X
  3. 对 C 做特征值分解
  4. 取前 k 个最大特征值对应的特征向量 → 投影矩阵
import numpy as np

class SimplePCA:
def __init__(self, n_components=2):
self.n_components = n_components

def fit(self, X):
# 中心化
self.mean_ = X.mean(axis=0)
X_centered = X - self.mean_

# 协方差矩阵
cov = np.cov(X_centered.T)

# 特征值分解
eigenvalues, eigenvectors = np.linalg.eigh(cov)

# 取最大的 n_components 个
idx = np.argsort(eigenvalues)[::-1]
self.components_ = eigenvectors[:, idx[:self.n_components]]
self.explained_variance_ = eigenvalues[idx[:self.n_components]]

return self

def transform(self, X):
X_centered = X - self.mean_
return X_centered @ self.components_

def fit_transform(self, X):
self.fit(X)
return self.transform(X)

Scikit-learn 实现

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

digits = load_digits()
X, y = digits.data, digits.target

# 64 维 → 2 维可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X)

plt.scatter(X_pca[:, 0], X_pca[:, 1], c=y, cmap='tab10', alpha=0.6)
plt.colorbar()

# 查看保留的方差比例
print(f"每个主成分解释的方差: {pca.explained_variance_ratio_}")
print(f"累计方差: {pca.explained_variance_ratio_.cumsum()}")

如何选择主成分数量

pca = PCA().fit(X)

# 累计方差图
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.axhline(y=0.95, color='r', linestyle='--')
plt.xlabel('Number of Components')
plt.ylabel('Cumulative Explained Variance')

# 取保留 95% 方差的组件数
k = np.argmax(np.cumsum(pca.explained_variance_ratio_) >= 0.95) + 1
print(f"保留 95% 方差需要 {k} 个主成分")

也可以用 PCA(n_components=0.95) 直接指定保留的方差比例。

应用场景

1. 降维可视化

高维数据降到 2D/3D 观察分布:

from sklearn.decomposition import PCA

pca = PCA(n_components=2)
X_vis = pca.fit_transform(X)

2. 去噪

pca = PCA(n_components=0.95).fit(X) # 保留 95% 方差
X_denoised = pca.inverse_transform(pca.transform(X))

丢弃小方差的维度往往对应噪声。

3. 加速训练

from sklearn.pipeline import Pipeline
from sklearn.linear_model import LogisticRegression

pipe = Pipeline([
('pca', PCA(n_components=50)),
('lr', LogisticRegression()),
])
pipe.fit(X_train, y_train)

PCA vs t-SNE vs UMAP

方法特点适用场景
PCA线性、快速、可逆、可解释降维后做 ML、去噪
t-SNE保留局部结构、慢可视化探索
UMAP保留局部+部分全局、比 t-SNE 快可视化 + 后续 ML

注意:t-SNE 和 UMAP 适合可视化探索,但降维后的特征不适合直接用于下游 ML 任务(距离含义已改变)。

总结

特性说明
优点简单快速、去噪、消除特征共线性、可逆
缺点只捕捉线性关系、主成分难解释、假设方差=信息
适用场景数据预处理(降维)、去噪、高维数据可视化