一、PCA(主成分分析)核心原理

即主成分分析技术,又称主分量分析技术,旨在利用降维的思想,把多指标转化为少数几个综合指标。在统计学中,主成分分析PCA是一种简化数据集的技术。它是一个线性变换。这个变换把数据变换到一个新的坐标系统中,使得任何数据投影的第一大方差在第一个坐标(称为第一主成分)上,第二大方差在第二个坐标(第二主成分)上,依次类推。主成分分析经常用于减少数据集的维数,同时保持数据集的对方差贡献最大的特征。这是通过保留低阶主成分,忽略高阶主成分做到的。这样低阶成分往往能够保留住数据的最重要方面。但是,这也不是一定的,要视具体应用而定。
1️⃣ 数学本质
  • 目标:找到一组正交基,使得数据投影到这些基上的方差最大化
  • 数学推导
    1. 计算协方差矩阵 C=1nXTXC = \frac{1}{n}X^TXC=n1XTX
    2. 特征值分解 C=VΛVTC = V\Lambda V^TC=VΛVT
    3. 选择前k大特征值对应的特征向量组成投影矩阵 WkW_kWk
2️⃣ 方差解释率
  • 单个主成分λi∑λj\frac{\lambda_i}{\sum \lambda_j}λjλi
  • 累计解释率∑i=1kλi∑λj\frac{\sum_{i=1}^k \lambda_i}{\sum \lambda_j}λji=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️⃣ 数据预处理流程
原始数据
缺失值处理
异常值处理
标准化/Z-score
PCA降维
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均值:(1+3+5)/3 = 3
    • 特征2均值:(2+4+6)/3 = 4
  2. 中心化(每个特征减去均值):

原始数据 → 中心化后数据
[1,2] → [-2, -2]
[3,4] → [0, 0]
[5,6] → [2, 2]
步骤3:计算协方差矩阵

协方差矩阵公式:

C=1n−1XTX C = \frac{1}{n-1}X^TX C=n11XTX

实际计算:

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−λ444−λ∣=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λ)216=0λ28λ=0λ(λ8)=0

得到特征值:

λ1=8,λ2=0 \lambda_1 = 8, \quad \lambda_2 = 0 λ1=8,λ2=0

步骤5:求特征向量

对于λ=8
解方程 (C−8I)v=0(C - 8I)v = 0(C8I)v=0

[−444−4][v1v2]=0 \begin{bmatrix} -4 & 4 \\ 4 & -4 \end{bmatrix} \begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = 0 [4444][v1v2]=0

v1=v2v_1 = v_2v1=v2,归一化得:

v1=[1212] v_1 = \begin{bmatrix} \frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} v1=[2 12 1]

对于λ=0
解方程 (C−0I)v=0(C - 0I)v = 0(C0I)v=0

[4444][v1v2]=0 \begin{bmatrix} 4 & 4 \\ 4 & 4 \end{bmatrix} \begin{bmatrix} v_1 \\ v_2 \end{bmatrix} = 0 [4444][v1v2]=0

v1=−v2v_1 = -v_2v1=v2,归一化得:

v2=[−1212] v_2 = \begin{bmatrix} -\frac{1}{\sqrt{2}} \\ \frac{1}{\sqrt{2}} \end{bmatrix} v2=[2 12 1]


几何解释可视化

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()

在这里插入图片描述

关键结论

  1. PC1方向(蓝色箭头):数据在该方向的投影方差最大(λ=8)
  2. PC2方向(绿色箭头):投影方差为0 → 数据在该方向无变化
  3. 降维选择:只需保留PC1即可100%保留原始信息(因为第二个主成分方差为0)

思考题

假设有以下数据:

X_new = np.array([[2,3], [4,5], [6,7]])

尝试手工计算其协方差矩阵和主成分方向,验证是否也满足其中一个主成分方差为0?

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐