主成分分析(PCA)原理与实现详解
2025-07-10 07:18:16作者:尤辰城Agatha
引言
主成分分析(Principal Component Analysis,PCA)是数据降维中最常用的技术之一。本教程将深入讲解PCA的数学原理,并通过Python代码实现完整的PCA流程。我们将从协方差矩阵的特征分解开始,逐步展示如何通过投影数据到特征向量来实现降维。
理论基础
协方差矩阵与特征分解
PCA的核心思想是通过线性变换将原始数据投影到一个新的坐标系中,这个坐标系的基向量是数据协方差矩阵的特征向量。具体步骤如下:
-
计算协方差矩阵:对于中心化后的数据矩阵X,协方差矩阵Σ的计算公式为:
Σ = (1/N) XᵀX
-
特征分解:对协方差矩阵进行特征分解,得到特征值λ和对应的特征向量v:
Σv = λv
-
选择主成分:按照特征值从大到小排序,选择前k个特征向量作为新的基。
数据投影
将原始数据X投影到选定的特征向量上:
Y = XW
其中W是由前k个特征向量组成的矩阵。
代码实现
数据准备
首先我们生成二维高斯分布数据:
import numpy as np
import matplotlib.pyplot as plt
# 定义协方差矩阵参数
var_1 = 1
var_2 = 1
corr_coef = 0.8
# 计算协方差矩阵
cov = corr_coef * np.sqrt(var_1 * var_2)
cov_matrix = np.array([[var_1, cov], [cov, var_2]])
# 生成数据
mean = np.array([0, 0])
X = np.random.multivariate_normal(mean, cov_matrix, size=1000)
可视化原始数据
def plot_data(X):
fig = plt.figure(figsize=[8, 4])
# 绘制两个神经元的时序活动
plt.subplot(1, 2, 1)
plt.plot(X[:, 0], color='k')
plt.plot(X[:, 1], color='r')
plt.xlabel('Sample Number')
plt.ylabel('Activity')
# 绘制散点图
plt.subplot(1, 2, 2)
plt.plot(X[:, 0], X[:, 1], '.', color=[.5, .5, .5])
plt.xlabel('Neuron 1 activity')
plt.ylabel('Neuron 2 activity')
plt.title(f'Sample corr: {np.corrcoef(X.T)[0,1]:.2f}')
plt.show()
plot_data(X)
计算协方差矩阵和特征分解
# 计算样本协方差矩阵
cov_matrix_sample = np.cov(X.T)
# 特征分解
evals, evectors = np.linalg.eigh(cov_matrix_sample)
# 按特征值降序排列
evals, evectors = evals[::-1], evectors[:, ::-1]
print("特征值:", evals)
print("特征向量:\n", evectors)
可视化特征向量
def plot_basis_vectors(X, W):
plt.figure(figsize=[6, 6])
plt.plot(X[:, 0], X[:, 1], '.', color=[.5, .5, .5], alpha=0.5)
plt.axis('equal')
# 绘制特征向量
colors = ['r', 'b']
for i in range(2):
plt.arrow(0, 0, W[0, i], W[1, i],
color=colors[i], width=0.02, head_width=0.1)
plt.text(W[0, i]*1.2, W[1, i]*1.2, f'PC{i+1}', color=colors[i])
plt.xlabel('Neuron 1 activity')
plt.ylabel('Neuron 2 activity')
plt.show()
plot_basis_vectors(X, evectors)
数据投影与降维
# 投影到主成分空间
Y = X @ evectors
# 可视化投影后数据
def plot_projected_data(Y):
plt.figure(figsize=[12, 4])
# 绘制主成分时序
plt.subplot(1, 2, 1)
plt.plot(Y[:, 0], 'r', label='PC1')
plt.plot(Y[:, 1], 'b', label='PC2')
plt.xlabel('Sample number')
plt.ylabel('Projection value')
plt.legend()
# 绘制主成分散点图
plt.subplot(1, 2, 2)
plt.plot(Y[:, 0], Y[:, 1], '.', color=[.5, .5, .5])
plt.xlabel('Projection PC1')
plt.ylabel('Projection PC2')
plt.title(f'Sample corr: {np.corrcoef(Y.T)[0,1]:.2f}')
plt.axis('equal')
plt.show()
plot_projected_data(Y)
特征值分析(碎石图)
def plot_eigenvalues(evals):
plt.figure(figsize=[6, 4])
plt.plot(np.arange(1, len(evals)+1, evals, 'o-k')
plt.xlabel('Principal Component')
plt.ylabel('Eigenvalue')
plt.title('Scree Plot')
plt.xticks(np.arange(1, len(evals)+1)
plt.show()
plot_eigenvalues(evals)
实际应用建议
-
数据标准化:在应用PCA前,通常需要对数据进行标准化处理(均值为0,方差为1),特别是当不同特征的量纲差异较大时。
-
主成分选择:可以通过以下方法选择保留的主成分数量:
- 保留解释方差累计达到阈值(如95%)的成分
- 选择特征值大于平均值的成分
- 观察碎石图中"肘部"位置
-
解释性:主成分通常是原始特征的线性组合,可以分析特征向量中的权重来理解每个主成分的含义。
总结
本教程详细介绍了PCA的数学原理和实现步骤:
- 计算数据的协方差矩阵
- 对协方差矩阵进行特征分解
- 按特征值排序选择主成分
- 将数据投影到选定的主成分上
PCA是一种强大的降维工具,能够有效减少数据维度同时保留大部分信息。理解PCA的原理对于正确应用和解释结果至关重要。