26·数据处理进阶

主成分分析(PCA)降维

dimensionality-reductionpca

第26课:主成分分析(PCA)降维

学习目标

完成本课学习后,你将能够:

  1. 理解PCA降维的核心思想与几何意义。
  2. 掌握使用scikit-learn库对数据进行PCA降维的完整流程。
  3. 知道如何通过累积方差贡献率选择合适的主成分数量。
  4. 能够将PCA应用于实际数据预处理任务中。

核心概念

想象一下,你用相机从不同角度拍了一张桌子的立体照片(高维数据),但最终需要在一张平面的纸(低维空间)上画出桌子。主成分分析就是帮你找到最佳拍摄角度的方法,让这张平面照片能最大程度地保留桌子的立体特征信息。

在数学上,PCA的目标是找到数据变化(方差)最大的方向。第一个主成分(PC1)就是数据方差最大的方向,第二个主成分(PC2)是与PC1垂直且方差第二大的方向,以此类推。通过保留前几个主成分,我们就能用更少的维度(变量)来近似表示原始数据,同时尽可能多地保留数据中的信息。

核心步骤简化版:

  1. 数据标准化:将每个特征缩放到均值为0、方差为1。这是PCA的前提,因为PCA对方差敏感。
  2. 计算协方差矩阵:衡量各特征之间的相关性。
  3. 特征分解:对协方差矩阵进行分解,得到特征值和特征向量。特征向量就是主成分的方向,特征值代表该方向的方差大小。
  4. 选择主成分:根据特征值(或解释的方差比例)从大到小排序,选择前k个特征向量构成投影矩阵。
  5. 数据转换:将原始数据投影到选定的主成分上,得到降维后的数据。

代码示例

1. 基础PCA降维流程

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

# 加载经典鸢尾花数据集 (4个特征)
iris = load_iris()
X = iris.data
y = iris.target
feature_names = iris.feature_names
target_names = iris.target_names

print(f"原始数据形状: {X.shape}") # (150, 4)

# 第1步:数据标准化 (至关重要!)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 第2步:创建PCA对象并拟合数据
# 我们暂时先保留所有主成分,以便查看所有特征值
pca = PCA() # n_components 默认为保留所有成分
X_pca = pca.fit_transform(X_scaled)

# 查看PCA结果
print(f"降维后数据形状: {X_pca.shape}") # 仍然是 (150, 4),因为没指定数量

# 第3步:分析方差贡献率
explained_variance_ratio = pca.explained_variance_ratio_
cumulative_variance_ratio = np.cumsum(explained_variance_ratio)

print("各主成分方差贡献率:", explained_variance_ratio)
print("累积方差贡献率:", cumulative_variance_ratio)

# 第4步:可视化 (前两个主成分)
plt.figure(figsize=(10, 6))
colors = ['navy', 'turquoise', 'darkorange']
lw = 2

for color, i, target_name in zip(colors, [0, 1, 2], target_names):
    plt.scatter(X_pca[y == i, 0], X_pca[y == i, 1], color=color, alpha=.8, lw=lw,
                label=target_name)
plt.legend(loc='best', shadow=False, scatterpoints=1)
plt.title('PCA of IRIS dataset')
plt.xlabel('第一主成分 (PC1)')
plt.ylabel('第二主成分 (PC2)')
plt.grid(True, alpha=0.3)
plt.show()

2. 选择主成分数量

# 根据累积方差贡献率选择主成分
# 设定一个阈值,例如我们希望保留95%的信息
threshold = 0.95
n_components = np.argmax(cumulative_variance_ratio >= threshold) + 1
print(f"保留 {threshold*100}% 方差所需最少主成分数: {n_components}")

# 使用选择的n_components重新进行PCA
pca_optimal = PCA(n_components=n_components)
X_pca_optimal = pca_optimal.fit_transform(X_scaled)

print(f"优化后的降维数据形状: {X_pca_optimal.shape}") # (150, 2) 或 (150, 3)

# 可视化方差贡献率
plt.figure(figsize=(8, 5))
plt.bar(range(1, len(explained_variance_ratio) + 1), explained_variance_ratio, alpha=0.5, align='center',
        label='单个方差贡献率')
plt.step(range(1, len(cumulative_variance_ratio) + 1), cumulative_variance_ratio, where='mid',
         label='累积方差贡献率')
plt.ylabel('方差贡献率')
plt.xlabel('主成分')
plt.legend(loc='best')
plt.tight_layout()
plt.axhline(y=threshold, color='r', linestyle='--', label=f'{threshold*100}% 阈值')
plt.show()

实践练习

练习1:基础降维

sklearn.datasets中的digits手写数字数据集(64个像素特征)进行PCA降维。

  1. 对数据标准化。
  2. 执行PCA,保留使得累积方差贡献率 >= 90% 的主成分数量。
  3. 输出最终降维后的数据形状。 预期输出示例降维后数据形状: (1797, X),其中X是一个整数。

练习2:可视化与解释

使用练习1中降维后的数据(前两个主成分)绘制散点图,并用不同的颜色区分不同的数字(0-9)。 预期输出:一个包含10种颜色的散点图,每个点代表一个数字样本,可以观察数字在二维空间的聚类分布。

练习3:PCA在模型中的应用

  1. 将原始数据(digits数据集)和PCA降维后的数据分别划分为训练集和测试集。
  2. 使用逻辑回归或支持向量机等分类器,分别在原始数据和降维后的数据上训练和评估模型。
  3. 比较两者的分类准确率和训练时间。 预期输出:降维后的数据在准确率损失很小的情况下,模型训练速度有显著提升。

常见错误

  1. 忘记数据标准化:PCA是基于方差的算法,如果特征尺度差异巨大,方差大的特征会主导主成分方向,导致结果毫无意义。StandardScaler是必须的。
  2. 过度降维:保留的主成分过少,导致丢失过多关键信息,模型性能下降严重。应根据累积方差贡献率或下游任务性能来合理选择。
  3. 误解主成分含义:每个主成分是原始特征的线性组合,其物理含义通常不如原始特征直观。不要试图直接解释某个主成分对应“什么”,而应关注其在降维和可视化中的作用。
  4. 对非线性数据使用PCA:PCA是一种线性降维方法。如果数据结构本质上是高度非线性的(如瑞士卷),PCA效果不佳,此时应考虑使用t-SNE、UMAP等非线性降维技术。

小结

本节课我们学习了主成分分析这一强大的降维工具。

  • 核心思想:通过正交变换,将原始特征转换为一组线性无关的新特征(主成分),并按方差(信息量)大小排序。
  • 关键步骤标准化 -> 计算协方差矩阵/特征分解 -> 选择主成分 -> 数据投影
  • 选择主成分:利用累积方差贡献率曲线,选择在达到特定信息保留阈值(如95%)时的最小主成分数。
  • 应用场景:数据可视化(降至2-3维)、数据压缩、去除特征间相关性、提升模型训练效率(作为预处理步骤)。
  • 重要提醒:数据必须标准化,并注意PCA的线性假设。

掌握PCA,你就拥有了处理高维数据的一把利器。在下一课中,我们将学习如何运用这些预处理技术,结合探索性数据分析,更深入地理解数据集。

练习编辑器

rust
Loading...

继续学习

完成本课后,建议继续学习下一课「探索性数据分析(EDA)方法与实践」 以巩固所学知识。