PCA 数学原理:协方差矩阵、特征值分解、主成分
说实话,很多讲 PCA 的教程一上来就扔公式。
我以前刚学的时候也懵。
但后来在项目中反复调优,才真正摸透这三个东西:协方差矩阵、特征值分解、主成分。
说白了,它们就是 PCA 的三个齿轮。理解清楚,后面用什么降维都不慌。
1. 数据中心化 —— 起点
PCA 的第一步,不是算协方差,是去均值。
为什么要去?
因为协方差本质是衡量变量之间的“共同偏离”。如果均值都不对齐,你算出来的协方差会被整体偏移带偏。
import numpy as np
# 原始数据 X,形状 (n_samples, n_features)
X_centered = X - np.mean(X, axis=0)
就这么一行。但这一步决定了后面所有计算的有效性。
我在做一个用户行为聚类项目时,一开始没去均值,结果第一主成分几乎全是用户活跃度均值本身——废的。
2. 协方差矩阵 —— 变量关系的快照
中心化之后,我们就来算协方差矩阵。
公式长这样:
C = (1 / (n-1)) * X_centered.T @ X_centered
结果是一个 d × d 的对称矩阵(d 是特征数)。
它的对角线上是每个特征的方差,非对角线上是两两特征之间的协方差。
这里有个关键点:
- 如果两个特征正相关,协方差 > 0
- 负相关 < 0
- 几乎无关 ≈ 0
你看,这个矩阵先把所有“特征之间的关系”浓缩成一个数字快照。PCA 后面的所有操作,都基于这个快照。
3. 特征值分解 —— 找到“主方向”
拿到协方差矩阵 C 之后,我们要做特征值分解:
eigenvalues, eigenvectors = np.linalg.eig(C)
或者用更稳定的 SVD:
U, S, Vt = np.linalg.svd(X_centered, full_matrices=False)
eigenvalues = S**2 / (n-1)
eigenvectors = Vt.T
每个特征值对应一个特征向量。
特征值的大小,代表这个方向上的“数据方差”。
特征向量本身,就是一个新的坐标轴(即主成分方向)。
你想想看,方差越大,说明数据在这个方向上散得越开,信息量越大。我们保留最大的 k 个特征值对应的方向,就完成了降维。
| 概念 | 含义 | 在 PCA 中的作用 |
|---|---|---|
| 特征值 λ | 该方向上的方差大小 | 决定主成分的“贡献率” |
| 特征向量 v | 该方向的空间向量 | 组成新坐标系的基 |
| 累计方差比 | 前 k 个 λ 之和 / 总 λ 之和 | 选多少个主成分的依据 |
4. 主成分 —— 降维后的新数据
最后一步:投影。
选 top-k 个特征向量组成矩阵 W(d × k)。
降维后的数据 Z = X_centered @ W。
k = 2 # 降到2维
top_k_eigenvectors = eigenvectors[:, :k] # 取前k列
Z = X_centered @ top_k_eigenvectors
Z 就是新的特征空间,每一列是一个主成分,互不相关(正交)。
而且第一主成分的方差最大,第二主成分次之……
整体流程一图看
下面这张 SVG 把上面三步串起来了。
小结
我个人经验是:把 PCA 的数学原理拆成去均值 → 算协方差 → 特征分解 → 选主成分 → 投影这五步,能让你真正理解它为什么能降维。
尤其注意协方差矩阵的质量。如果特征数远大于样本数,矩阵秩亏,特征值会有一堆零。这时候可以用随机 PCA 或核方法,但那是后话了。
嗯,先把基础打牢。项目中遇到数据行列不平衡时,你就能判断该不该用 PCA,还是先做特征选择。