
PCA ( Principal Component Analysis ,主成分分析) 是一种无监督降维方法:在尽量保留方差(信息)的前提下,把数据投影到更低维空间。
核心思想
高维数据里,很多方向变化很小(冗余)。PCA 找一组正交的新坐标轴(主成分),使得:
- 第 1 主成分:投影后方差最大
- 第 2 主成分:与第 1 正交,且方差次大
- 依此类推
用前
个主成分近似原数据 → 降维、去相关、便于可视化。
计算步骤(对应代码)
| 步骤 | 含义 | notebook |
|---|---|---|
| 1. 中心化/标准化 | 去均值,消除量纲影响 | calc_cov 里对 X 标准化 |
| 2. 协方差矩阵 | 刻画特征间相关与方差 | ![]() |
| 3. 特征分解 | ![]() |
np.linalg.eig |
4. 排序取前 k ![]() |
大 → 该方向信息多 |
argsort()::-1,取前 n_components |
| 5. 投影 | ( 为前 个特征向量) |
np.matmul(X, eigenvectors) |
直观理解
- 特征值
:该主成分能解释多少方差 - 特征向量
:主成分方向 - 降到 2/3 维后画散点(鸢尾花示例),是为了看类别是否仍大致可分
和 LDA 的区别
| PCA | LDA | |
|---|---|---|
| 是否用标签 | 否(无监督) | 是(有监督) |
| 目标 | 方差最大 | 类间大、类内小 |
| 用途 | 降维、压缩、可视化 | 分类相关的有监督降维 |
一句话: PCA = 对协方差矩阵做特征分解,用方差最大的几个方向做投影,实现降维。
** **代码** **
import numpy as np
class PCA():
# 计算协方差矩阵
def calc_cov(self, X):
m = X.shape[0]
# 数据标准化
X = (X - np.mean(X, axis=0)) / np.var(X, axis=0)
return 1 / m * np.matmul(X.T, X)
def pca(self, X, n_components):
# 计算协方差矩阵
cov_matrix = self.calc_cov(X)
# 计算协方差矩阵的特征值和对应特征向量
eigenvalues, eigenvectors = np.linalg.eig(cov_matrix)
# 对特征值排序
idx = eigenvalues.argsort()[::-1]
# 取最大的前n_component组
eigenvectors = eigenvectors[:, idx]
eigenvectors = eigenvectors[:, :n_components]
# Y=PX转换
return np.matmul(X, eigenvectors)
** **代码** **
from sklearn import datasets
import matplotlib.pyplot as plt
# 导入sklearn数据集
iris = datasets.load_iris()
X = iris.data
y = iris.target
# 将数据降维到3个主成分
X_trans = PCA().pca(X, 3)
# 颜色列表
colors = ['navy', 'turquoise', 'darkorange']
# 绘制不同类别
for c, i, target_name in zip(colors, [0,1,2], iris.target_names):
plt.scatter(X_trans[y == i, 0], X_trans[y == i, 1],
color=c, lw=2, label=target_name)
# 添加图例
plt.legend()
plt.show();

** **代码** **
# 导入sklearn降维模块
from sklearn import decomposition
# 创建pca模型实例,主成分个数为3个
pca = decomposition.PCA(n_components=3)
# 模型拟合
pca.fit(X)
# 拟合模型并将模型应用于数据X
X_trans = pca.transform(X)
# 颜色列表
colors = ['navy', 'turquoise', 'darkorange']
# 绘制不同类别
for c, i, target_name in zip(colors, [0,1,2], iris.target_names):
plt.scatter(X_trans[y == i, 0], X_trans[y == i, 1],
color=c, lw=2, label=target_name)
# 添加图例
plt.legend()
plt.show();

标准化


大 → 该方向信息多
(
为前
个特征向量)