PCA(主成分分析)核心原理
一、PCA(主成分分析)核心原理
即主成分分析技术,又称主分量分析技术,旨在利用降维的思想,把多指标转化为少数几个综合指标。在统计学中,主成分分析PCA是一种简化数据集的技术。它是一个线性变换。这个变换把数据变换到一个新的坐标系统中,使得任何数据投影的第一大方差在第一个坐标(称为第一主成分)上,第二大方差在第二个坐标(第二主成分)上,依次类推。主成分分析经常用于减少数据集的维数,同时保持数据集的对方差贡献最大的特征。这是通过保留低阶主成分,忽略高阶主成分做到的。这样低阶成分往往能够保留住数据的最重要方面。但是,这也不是一定的,要视具体应用而定。
1️⃣ 数学本质
- 目标:找到一组正交基,使得数据投影到这些基上的方差最大化
- 数学推导:
- 计算协方差矩阵 C = 1 n X T X C = \frac{1}{n}X^TX C=n1XTX
- 特征值分解 C = V Λ V T C = V\Lambda V^T C=VΛVT
- 选择前k大特征值对应的特征向量组成投影矩阵 W k W_k Wk
2️⃣ 方差解释率
- 单个主成分: λ i ∑ λ j \frac{\lambda_i}{\sum \lambda_j} ∑λjλi
- 累计解释率: ∑ i = 1 k λ i ∑ λ j \frac{\sum_{i=1}^k \lambda_i}{\sum \lambda_j} ∑λj∑i=1kλi
二、Python代码实现
1️⃣ 基础应用(Scikit-learn)
from sklearn.decomposition import PCA
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import load_iris
# 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(load_iris().data)
# PCA降维
pca = PCA(n_components=0.95) # 保留95%方差
X_pca = pca.fit_transform(X_scaled)
print(f"原始维度: {X_scaled.shape[1]}")
print(f"降维后维度: {X_pca.shape[1]}")
print(f"各主成分方差解释率: {pca.explained_variance_ratio_}")
2️⃣ 特征可视化
import matplotlib.pyplot as plt
plt.scatter(X_pca[:,0], X_pca[:,1], c=load_iris().target)
plt.xlabel('PC1 ({:.1f}%)'.format(pca.explained_variance_ratio_[0]*100))
plt.ylabel('PC2 ({:.1f}%)'.format(pca.explained_variance_ratio_[1]*100))
plt.title('PCA Projection')
plt.show()
三、关键参数解析
参数 | 类型 | 作用 | 推荐设置 |
---|---|---|---|
n_components | int/float | 指定保留主成分数或方差比例 | 0.85~0.99(常用0.95) |
svd_solver | str | 选择SVD求解器 | ‘auto’(自动选择) |
whiten | bool | 是否白化数据 | 需要时设为True |
四、工业级最佳实践
1️⃣ 数据预处理流程
2️⃣ 主成分数量选择
- 肘部法则:绘制累计方差曲线,选择拐点
pca = PCA().fit(X_scaled)
plt.plot(np.cumsum(pca.explained_variance_ratio_))
plt.axhline(y=0.95, color='r', linestyle='--')
plt.xlabel('主成分数量')
plt.ylabel('累计方差解释率')
五、应用场景与案例
领域 | 应用方式 | 案例效果 |
---|---|---|
图像处理 | 人脸识别(Eigenfaces) | 500x500 → 100维,准确率保持90%+ |
金融风控 | 去除多重共线性 | VIF从50降至<5 |
生物信息学 | 基因表达数据降维 | 20000基因 → 50主成分 |
推荐系统 | 用户-物品矩阵降维 | 提升协同过滤效率3倍 |
六、常见问题解答
1️⃣ PCA前为什么要标准化?
- 消除量纲影响,防止方差大的特征主导主成分方向
2️⃣ PCA与LDA的区别?
特性 | PCA | LDA |
---|---|---|
监督性 | 无监督 | 有监督 |
优化目标 | 最大方差 | 类间最大/类内最小 |
降维上限 | 无限制 | 最多c-1维(c为类别数) |
3️⃣ PCA是否损失信息?
- 是,但通过控制累计方差解释率(如≥95%)可最大限度保留有效信息
七、进阶技巧
1️⃣ 增量PCA(处理大数据)
from sklearn.decomposition import IncrementalPCA
ipca = IncrementalPCA(n_components=10, batch_size=100)
for batch in np.array_split(X_scaled, 10):
ipca.partial_fit(batch)
X_ipca = ipca.transform(X_scaled)
2️⃣ 核PCA(处理非线性)
from sklearn.decomposition import KernelPCA
kpca = KernelPCA(n_components=2, kernel='rbf', gamma=0.04)
X_kpca = kpca.fit_transform(X_scaled)
八、数学验证(手工计算)详解
让我们通过一个简单示例逐步推导,理解PCA的数学本质:
步骤1:准备数据
X = np.array([[1,2],
[3,4],
[5,6]]) # 3个样本,2个特征
步骤2:中心化数据
-
计算每个特征的均值:
- 特征1均值:
(1+3+5)/3 = 3
- 特征2均值:
(2+4+6)/3 = 4
- 特征1均值:
-
中心化(每个特征减去均值):
原始数据 → 中心化后数据
[1,2] → [-2, -2]
[3,4] → [0, 0]
[5,6] → [2, 2]
步骤3:计算协方差矩阵
协方差矩阵公式:
C = 1 n − 1 X T X C = \frac{1}{n-1}X^TX C=n−11XTX
实际计算:
X_centered = np.array([[-2, -2],
[ 0, 0],
[ 2, 2]])
C = np.cov(X_centered.T) # 转置后计算协方差矩阵
print(C)
# 输出:[[4. 4.]
# [4. 4.]]
步骤4:特征值分解
求解特征方程:
∣ C − λ I ∣ = 0 |C - \lambda I| = 0 ∣C−λI∣=0
即:
∣ 4 − λ 4 4 4 − λ ∣ = 0 \begin{vmatrix} 4-\lambda & 4 \\ 4 & 4-\lambda \end{vmatrix} = 0 4−λ444−λ =0
展开方程:
( 4 − λ ) 2 − 16 = 0 λ 2 − 8 λ = 0 λ ( λ − 8 ) = 0 (4-\lambda)^2 - 16 = 0 \\ \lambda^2 - 8\lambda = 0 \\ \lambda(\lambda - 8) = 0 (4−λ)2−16=0λ2−8λ=0λ(λ−8)=0
得到特征值:
λ 1 = 8 , λ 2 = 0 \lambda_1 = 8, \quad \lambda_2 = 0 λ1=8,λ2=0
步骤5:求特征向量
对于λ=8:
解方程
(
C
−
8
I
)
v
=
0
(C - 8I)v = 0
(C−8I)v=0:
[ − 4 4 4 − 4 ] [ v 1 v 2 ] = 0 \begin{bmatrix} -4 & 4 \\ 4 & -4 \end{bmatrix} \begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = 0 [−444−4][v1v2]=0
得 v 1 = v 2 v_1 = v_2 v1=v2,归一化得:
v 1 = [ 1 2 1 2 ] v_1 = \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} v1=[2121]
对于λ=0:
解方程
(
C
−
0
I
)
v
=
0
(C - 0I)v = 0
(C−0I)v=0:
[ 4 4 4 4 ] [ v 1 v 2 ] = 0 \begin{bmatrix} 4 & 4 \\ 4 & 4 \end{bmatrix} \begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = 0 [4444][v1v2]=0
得 v 1 = − v 2 v_1 = -v_2 v1=−v2,归一化得:
v 2 = [ − 1 2 1 2 ] v_2 = \begin{bmatrix} -\frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} v2=[−2121]
几何解释可视化
import matplotlib.pyplot as plt
# 原始数据与主成分方向
plt.figure(figsize=(10,4))
# 原始数据
plt.subplot(121)
plt.scatter(X_centered[:,0], X_centered[:,1], c='r')
plt.axhline(0, color='gray', lw=0.5)
plt.axvline(0, color='gray', lw=0.5)
plt.title("原始中心化数据")
plt.grid(True)
# 添加主成分方向
plt.subplot(122)
plt.scatter(X_centered[:,0], X_centered[:,1], c='r')
plt.quiver(0,0, 1/np.sqrt(2), 1/np.sqrt(2), angles='xy', scale_units='xy', scale=1, color='b', label='PC1 (λ=8)')
plt.quiver(0,0, -1/np.sqrt(2), 1/np.sqrt(2), angles='xy', scale_units='xy', scale=1, color='g', label='PC2 (λ=0)')
plt.axis('equal')
plt.title("主成分方向")
plt.legend()
plt.show()
关键结论
- PC1方向(蓝色箭头):数据在该方向的投影方差最大(λ=8)
- PC2方向(绿色箭头):投影方差为0 → 数据在该方向无变化
- 降维选择:只需保留PC1即可100%保留原始信息(因为第二个主成分方差为0)
思考题
假设有以下数据:
X_new = np.array([[2,3], [4,5], [6,7]])
尝试手工计算其协方差矩阵和主成分方向,验证是否也满足其中一个主成分方差为0?