Skip to content

主成分分析 PCA

PCA 的全称是 Principal Component Analysis,即主成分分析。它是一种常用的无监督降维方法,核心思想是:

在尽量保留数据方差信息的前提下,把高维数据投影到低维空间。

例如原始数据有 p 个特征,如果这些特征之间存在相关性,就可以用更少的 k 个新特征表示主要信息:

pk,k<p

PCA 常用于数据可视化、特征压缩、去噪、预处理等任务。

1. 样本矩阵

设一个随机变量有p个维度,那么第i个样本ai可以用p维向量来描述:

ri=[ai1,ai2,,aip]

样本集合有n个样本,每个维度的样本构成一个列向量c

cp=[a1a2an]

那么就形成了n×p的样本矩阵:

A=[r1r2rn]=[a11a12a1pa21a22a2pan1an2anp]=[c1,c2,,cp]

对每一列求均值,第p列的均值a¯p为:

a¯p=1ni=1nai,p

进行样本中心化,每一列的值减去该列的平均值,得到新矩阵:

X=[c1a¯1,c2a¯2,,cpa¯p]

后续推导默认使用中心化后的样本矩阵 X

2. 协方差矩阵

协方差计算公式为:

Cov(X,Y)=1n1i=1n(XiX¯)(YiY¯)

对于p维变量的协方差矩阵是分别计算每个维度之间的协方差:

C=[Cov(c1,c1)Cov(c1,c2)Cov(c1,cp)Cov(c2,c1)Cov(c2,c2)Cov(c2,cp)Cov(cp,c1)Cov(cp,c2)Cov(cp,cp)]

协方差矩阵的每个值Ci,j表示第i和第j个维度的协方差,而对角线的值表示方差。

把协方差公式展开后,提出公共的1n1项,得到:

C=1n1[i=1nai,1ai,1i=1nai,1ai,2i=1nai,1ai,pi=1nai,2ai,1i=1nai,2ai,2i=1nai,2ai,pi=1nai,pai,1i=1nai,pai,2i=1nai,pai,p]

由于此时样本已经中心化,a¯j=0,上述矩阵中的每个值可以写成两个列向量的内积:

i=1nai,pai,p=a1,pa1,p+a2,pa2,p++an,pan,p=[a1,pa2,pan,p]×[a1,pa2,pan,p]=cpTcp

整个矩阵可以最终化简得到:

C=1n1[c1Tc1c1Tc2c1Tcpc2Tc1c2Tc2c2TcpcpTc1cpTc2cpTcp]=1n1XTX

协方差矩阵大小为:

CRp×p

也就是说,协方差矩阵描述的是特征维度之间的相关性。

3. 第一主成分

求第一主成分 PC1 的问题可以转化为:寻找一个单位方向向量 v,使所有样本投影到这个方向后的方差最大。

约束条件为:

v2=1

i 个样本 xi 在方向 v 上的投影为:

zi=xiv

其中 xi 是中心化后矩阵 X 的第 i 行。

所有样本投影后的方差为:

s2=1n1i=1nzi2=1n1i=1n(xiv)2

写成矩阵形式:

z=Xv

因此:

s2=1n1zTz=1n1(Xv)T(Xv)=1n1vTXTXv=vTCv

所以 PCA 的第一主成分方向可以写成优化问题:

maxvvTCvs.t.vTv=1

4. 求极大值问题

最终将问题转变为已知条件下的最大值问题,可以利用拉格朗日乘数法求解:

maxs2=vTCvs.t.vTv=1

构造拉格朗日函数:

L(v,λ)=vTCvλ(vTv1)

对函数求偏导:

Lv=2Cv2λv=0

最后就得到了:

Cv=λv

这说明,v 是协方差矩阵 C 的特征向量,λ 是对应的特征值。

把上式带入目标函数:

vTCv=vT(λv)=λ(vTv)=λ

最大化目标函数就等价于最大化特征值 λ

因此:

第一主成分方向就是协方差矩阵最大特征值对应的特征向量。

5. 多个主成分

如果需要降到 k 维,就选择协方差矩阵 C 最大的前 k 个特征值对应的特征向量。

设这些特征向量组成矩阵:

Wk=[|||v1v2vk|||]Rp×k

则原始数据的低维表示为:

Z=XWk

其中:

ZRn×k

Z 就是降维后的样本矩阵。

如果想从低维空间近似重构原始数据,可以使用:

X^=ZWkT

因为 Z=XWk,所以:

X^=XWkWkT

k<p 时,X^ 只是对 X 的近似重构。

6. 解释方差比

每个特征值 λi 表示对应主成分方向上的方差大小。

如果特征值从大到小排列为:

λ1λ2λp

那么第 i 个主成分的解释方差比为:

ri=λij=1pλj

k 个主成分累计解释方差比为:

Rk=i=1kλij=1pλj

如果 Rk=0.95,表示前 k 个主成分保留了原始数据约 95% 的方差信息。

7. PCA 与 SVD 的关系

PCA 也可以通过奇异值分解实现。对中心化矩阵 X 做 SVD:

X=UΣVT

则协方差矩阵为:

C=1n1XTX

代入 SVD:

C=1n1(UΣVT)T(UΣVT)=1n1VΣTUTUΣVT=VΣTΣn1VT

因此,V 中的列向量就是 PCA 的主成分方向。

对应的特征值为:

λi=σi2n1

其中 σi 是第 i 个奇异值。

实际机器学习库中,PCA 常常通过 SVD 计算,而不是显式构造协方差矩阵。这在高维数据上更加稳定。

8. PCA 的基本步骤

PCA 的完整流程可以总结为:

  1. 对样本矩阵按列中心化。
  2. 计算协方差矩阵 C=1n1XTX
  3. C 做特征值分解。
  4. 选择最大前 k 个特征值对应的特征向量。
  5. 将原始数据投影到这些方向上:
Z=XWk

在实际使用中,还经常先对特征做标准化:

xij=xijμjσj

如果不同特征量纲差异很大,例如身高、收入、年龄混在一起,标准化通常是必要的。

9. sklearn 案例代码

下面用鸢尾花数据集演示 PCA。原始数据有 4 个特征,我们将其降到 2 维,方便可视化。

python
import matplotlib.pyplot as plt
from sklearn.datasets import load_iris
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA


iris = load_iris()
X = iris.data
y = iris.target

# PCA 对量纲敏感,通常先标准化
X_scaled = StandardScaler().fit_transform(X)

# 降到二维
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)

print("降维前形状:", X.shape)
print("降维后形状:", X_pca.shape)
print("解释方差比:", pca.explained_variance_ratio_)
print("累计解释方差比:", pca.explained_variance_ratio_.sum())

plt.figure(figsize=(6, 5))
for label in set(y):
    plt.scatter(
        X_pca[y == label, 0],
        X_pca[y == label, 1],
        label=iris.target_names[label],
        alpha=0.8,
    )

plt.xlabel("PC1")
plt.ylabel("PC2")
plt.title("Iris PCA")
plt.legend()
plt.tight_layout()
plt.show()

如果只想快速得到降维结果,最核心的代码是:

python
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA

X_scaled = StandardScaler().fit_transform(X)
X_pca = PCA(n_components=2).fit_transform(X_scaled)

10. 小结

PCA 的本质是寻找一组新的正交坐标轴,使数据投影后的方差尽可能大。

核心公式为:

C=1n1XTXCv=λvZ=XWk

其中最大特征值对应的特征向量就是第一主成分方向,前 k 个最大特征值对应的特征向量组成降维投影矩阵。

PCA 的优点是简单、可解释、计算高效;缺点是只能捕捉线性结构,并且对特征尺度比较敏感。