主成分分析法入门:从协方差矩阵到Python降维实战
2026/9/18 1:12:29 网站建设 项目流程

简介:这是一份面向数据统计初学者与数据分析人员的主成分分析法教学PPT,系统讲解主成分分析降维的核心原理、数学推导与完整计算流程,帮助读者解决多变量数据冗余、信息重叠而难以分析的问题。资源包仅有1个PPTX演示文稿,共19页,体积约199KB,轻量易用。目前已有61人学习。内容从主成分的定义与系数lij的确定原则切入,逐步展开相关系数矩阵的计算、特征方程Rv=λv的求解、特征向量归一化、贡献率与累计贡献率等关键步骤;并以农业生态经济系统区域单元数据为实例,涉及人口密度、人均耕地面积、森林覆盖率等多项指标,完整演示从数据标准化到主成分得分矩阵Z=XL的推导过程,帮助读者直观理解如何利用主成分识别影响系统的主要因素、简化后续分析。每页配有清晰的公式与表格,既适合教师备课作为课堂讲义,也适合学生自学并对照实例动手演算,快速掌握主成分分析在实际场景中的统计思想与应用技巧。

1. 一份 PPT 背后是主成分分析法最实用的课堂套路

打开“主成分分析法例子PPT学习教案.pptx”,屏幕上通常是四张散点图和一行批注:降维之后,数据分得更开了。这个标题对应的技术点,就是统计学里最常被当作“跑一遍就懂”的多元方法:主成分分析法。它解决的问题既简单又反直觉——主动丢掉一部分特征,模型效果反而更好,因为高维数据里大量信息互相冗余,真正决定数据结构的方向往往只有两三个。这篇博文按教学案例的推进方式,从投影原理讲到协方差矩阵的特征分解,再到 Python 可复现代码和参数设置,最后落在主成分解释上。读者只要装了 numpy 和 scikit-learn,就能从头到尾跟完整条线路。

2. 主成分分析法原理:从方差、协方差矩阵到特征向量

2.1 降维到底在降什么:寻找投影后方差最大的方向

先做一个思想实验。把一批二维数据点画在纸上,形状大致是一个斜着的椭圆。现在要求把数据压到一维,也就是找一条直线,把所有点投影上去。这条直线选 x 轴,投影点挤成一团;选 y 轴,结果类似。但如果沿着椭圆的长轴方向画一条线,投影点会拉开得很分散。散得越开,说明投影后的数据仍然保留了原始数据的大部分差异,点与点之间的区分度没有丢失。

差异在统计上就是方差。主成分分析法做的事情,一句话说:找一组相互正交的方向,让数据投影到这些方向上的方差依次最大。第一个方向是第一主成分,第二个方向是第二主成分,以此类推。实际操作中,原始特征通常有几十维,但前两三个主成分往往就占据了总方差的八成以上,剩余维度方差极小,近似理解为噪声。丢掉这些低方差方向,数据量变小,信息损失可控。

这里要区分两个容易混的概念:特征选择和特征抽取。特征选择是从原特征里挑几个留下,比如从年龄、收入、消费频次里选收入;主成分分析法是特征抽取,它把原始特征线性组合成新特征,每个主成分都含所有原始特征的贡献。新特征不再有直观的业务含义,这是为了降维付出的代价。

2.2 协方差矩阵为什么要“对角化”

要找方差最大的方向,不能只看单个特征的方差,还要看特征之间的相关性。设原始数据有 p 个特征,中心化后组成矩阵 X,形状是 n 行 p 列。特征的协方差矩阵 C 的定义是 X^T X 除以 n-1,对角线上的元素是每个特征的方差,非对角线元素是特征两两之间的协方差。协方差绝对值大,说明这两个特征同步变化,存在信息冗余。

现在的问题是:能不能找到一组新的坐标系,让数据在这个坐标系下的协方差矩阵变成对角阵?对角阵的非对角线元素全部为零,意味着新坐标系下各维度互不相关,冗余被拆干净了。这个新坐标系就是主成分方向。数学上,对一个实对称矩阵做特征分解,得到特征值和特征向量,特征向量就是新坐标系的基,特征值就是数据沿这个方向投影后的方差。

所以整个主成分分析法的核心就一句话:对协方差矩阵做特征分解,把特征值从大到小排序,取前 k 个特征向量组成投影矩阵。原始数据乘上这个投影矩阵,就得到降维后的主成分得分。在 sklearn 的 PCA 实现里,实际用的是奇异值分解 SVD,好处是数值更稳定,大数据集上不必先算出协方差矩阵再分解,但背后的几何含义与协方差特征分解完全一致。

2.3 从特征分解到降维得分:完整计算流程

把原理落到步骤上,标准流程一共五步。

第一步,中心化。每个特征减去自己的均值,让数据中心落在原点。如果特征量纲差异大,还要除以标准差做标准化,否则量纲大的特征会在协方差矩阵里主导方向。

第二步,计算协方差矩阵 C,公式为 (X^T X)/(n-1)。

第三步,对 C 做特征分解,得到特征值 λ1 ≥ λ2 ≥ … ≥ λp 和对应的特征向量。

第四步,按特征值大小排序,取前 k 个特征向量组成矩阵 W,形状是 p 行 k 列。特征值越大,对应主成分解释的方差越多。

第五步,计算主成分得分:T = XW。T 的形状是 n 行 k 列,每一行是原样本在 k 维新坐标系里的坐标,也就是降维后的结果。

整个过程中有两个关键参数:做了没有标准化,以及 k 取多少。前者影响方向,后者影响信息保留比例。理解了这两步,后面调参和排错的思路就清晰了。

3. 用鸢尾花数据集跑通主成分分析法的最小 Python 代码

3.1 数据准备:为什么要先标准化

教学案例最常用的是鸢尾花数据集,四个特征分别是花萼长、花萼宽、花瓣长、花瓣宽,共 150 条样本,三个类别各 50 条。这个数据集的优点是维度低、类别清晰,降维后可视化效果明显。

直接对原始数据做 PCA 有一个问题:花萼长和花瓣长的单位都是厘米,但数值范围不同,方差差异大。方差大的特征会在协方差矩阵里天然占据主导权重,这纯属量纲影响,和数据结构本身无关。所以标准做法是先标准化,让每个特征的均值为 0、方差为 1,然后再算协方差矩阵。

首先生成模拟数据和标准化的基础代码。

import numpy as np import matplotlib.pyplot as plt from sklearn.datasets import load_iris from sklearn.preprocessing import StandardScaler iris = load_iris() X = iris.data y = iris.target # 标准化:每个特征均值为0,标准差为1 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) print("原始数据形状:", X.shape) print("标准化后各特征均值:", X_scaled.mean(axis=0).round(6)) print("标准化后各特征标准差:", X_scaled.std(axis=0).round(6))

标准化这一步有两个参数会直接影响 PCA 结果:with_meanwith_std。默认都是True,含义是分别执行减均值、除标准差两步操作。如果数据本身已经是同一量纲且量级接近,比如图像像素值,可以只中心化不减标准差;如果特征单位差异大,比如收入、年龄、点击量混在一起,必须全部标准化。

3.2 手写 PCA 五步走,和 sklearn 结果对照

不依赖高级库手写一遍 PCA,能加深对原理的理解,实现起来也就十几行核心代码。下面的函数严格按照协方差矩阵特征分解的五步完成降维。

def pca_manual(X, n_components): # 1. 中心化 X_mean = X.mean(axis=0) X_centered = X - X_mean # 2. 计算协方差矩阵 cov_matrix = np.cov(X_centered, rowvar=False) # 3. 特征分解 eigenvalues, eigenvectors = np.linalg.eigh(cov_matrix) # 4. 特征值从大到小排序,取前n_components个 idx = np.argsort(eigenvalues)[::-1] eigenvalues = eigenvalues[idx] eigenvectors = eigenvectors[:, idx] top_eigenvectors = eigenvectors[:, :n_components] # 5. 投影得到主成分得分 X_pca = X_centered @ top_eigenvectors return X_pca, eigenvalues[:n_components] X_pca_manual, evals = pca_manual(X_scaled, 2) print("手写PCA降维后形状:", X_pca_manual.shape) print("前两个特征值:", evals)

代码说明:rowvar=Falsenp.cov把每一列当作一个特征,而不是把每一行当作一个变量;eigh专门用于对称矩阵的分解,返回的特征值已经按升序排列,所以后面要反转索引。argsort得到的是排序后的索引序列,[::-1]反转成降序。

注意这里用标准化后的X_scaled作为输入,函数内部没有再减一次均值。因为StandardScaler已经做过中心化,均值为 0,重复减均值不影响结果。如果直接传入原始数据,函数里的减均值步骤就会生效。这就是为什么前面强调标准化要先做好,整个流程里的每一步都以标准化后的数据为准。

用 sklearn 对照验证一下。

from sklearn.decomposition import PCA pca = PCA(n_components=2) X_pca_sklearn = pca.fit_transform(X_scaled) print("sklearn降维后形状:", X_pca_sklearn.shape) print("可解释方差比:", pca.explained_variance_ratio_) print("特征向量矩阵:\n", pca.components_)

两组结果对比时有一个常见的困惑来源:手写实现和 sklearn 输出的主成分得分可能符号相反,即第一列互为相反数。这是因为特征向量乘以 -1 后仍是单位正交向量,代表的方向不变。判别方法是看特征值的相对大小,特征值相同,方向就是同一组,正负号不影响后续的可视化分类结果。

3.3 主成分解读:载荷表与二维分布图

主成分分析的输出不能只看散点图,还要看每个主成分由哪些原始特征构成。特征向量矩阵components_就是载荷,每一行是一个主成分,每一列对应一个原始特征,数值表示该特征对主成分的贡献方向和大小。以鸢尾花数据集为例,投影后的载荷表大致如下。

主成分花萼长花萼宽花瓣长花瓣宽解释方差比
PC10.52-0.270.580.560.73
PC20.380.920.020.070.23

PC1 的载荷在花瓣长、花瓣宽、花萼长上都比较大,说明它主要代表花瓣相关特征的综合大小;PC2 在花萼宽上有几乎绝对的权重,基本就是花萼宽的单特征表达。两个主成分累计解释约 96% 的方差,剩下两个维度加起来不到 5%,丢掉它们是划算的。

可视化两种画法:一是降维后的散点图,二是碎石图。先看散点图。

plt.figure(figsize=(8, 6)) colors = ['#1f77b4', '#ff7f0e', '#2ca02c'] for cls in range(3): mask = y == cls plt.scatter(X_pca_sklearn[mask, 0], X_pca_sklearn[mask, 1], c=colors[cls], label=iris.target_names[cls], s=40, alpha=0.8) plt.xlabel('第一主成分') plt.ylabel('第二主成分') plt.legend() plt.title('鸢尾花数据集 PCA 降维结果') plt.grid(alpha=0.3) plt.savefig('iris_pca.png', dpi=120)

这段代码里每次用一个类别对应的布尔掩码mask从降维结果中取出对应样本,保证三个类别用不同颜色画在同一张图上。运行后能看到三个类别在二维平面上基本分离,山鸢尾与另外两类距离远,变色鸢尾和维吉尼亚鸢尾有部分重叠。如果觉得重叠区域影响教学效果,可以打印每个样本的主成分坐标,挑出重叠区域的样本编号,说明信息损失发生在哪里。

4. 主成分个数怎么选:方差解释率、碎石图与三个易错参数

4.1 累积方差解释率:选几个主成分的量化依据

每个主成分的特征值除以总特征值之和,就是这个主成分的方差解释比例。sklearn 里对应explained_variance_ratio_

累计到第 k 个的值,就是前 k 个主成分保留的信息占比。选择主成分个数最常用标准是累积方差解释率达到 80% 到 90%。鸢尾花数据取 2 个主成分就达到约 96%,所以 2 是合理选择。

看代码如何辅助决策。

pca_full = PCA(n_components=4) pca_full.fit(X_scaled) cum_ratio = np.cumsum(pca_full.explained_variance_ratio_) for i, r in enumerate(cum_ratio, start=1): print(f"前{i}个主成分累计解释方差: {r:.4f}")

输出结果能直接看到:取 1 个主成分保留约 73%,取 2 个约 96%,之后增长可以忽略。如果业务场景是数据可视化,取 2 到 3 个即可;如果目的是压缩特征做下游建模,可以设定阈值 0.9 然后取满足条件的最小 k。用PCA(n_components=0.95)可以让 sklearn 自动按达到 95% 解释方差的标准选出主成分个数。

4.2 碎石图与特征值:不要只盯累计到 0.8

碎石图是把特征值按大小顺序画成折线图或柱状图,用于观察特征值下降的拐点。原理是:真实信号对应的特征值明显偏大,而噪声对应的特征值小且彼此接近,折线会在某个点出现明显的转折。选取拐点之前的主成分,是比固定阈值更精细的做法。

绘制碎石图的代码很简短。

plt.figure(figsize=(8, 5)) plt.plot(range(1, 5), pca_full.explained_variance_, marker='o', linewidth=2) plt.xticks(range(1, 5)) plt.xlabel('主成分序号') plt.ylabel('特征值') plt.title('主成分碎石图') plt.grid(alpha=0.3) plt.savefig('scree_plot.png', dpi=120)

参数explained_variance_在 sklearn 的 PCA 对象里等价于特征值。在鸢尾花案例里看不到明显拐点,因为维度只有 4;但到了几十维的真实数据里,这种图的价值就体现出来了。需要注意,如果特征没有标准化,特征值大小受量纲影响,碎石图的拐点位置可能失真,这个问题在表格数据里尤其常见。

4.3 三个典型误用:特征重要性、先降维后归一化、混淆 LDA

第一个误用是把载荷当作特征重要性来解读。载荷绝对值大,只说明这个特征在主成分组合里权重大,不代表原始特征本身对预测目标重要。PCA 是无监督算法,它根本不看标签,只按方差找方向。如果目标是做分类或回归,应该用特征选择方法或模型的特征重要性属性来做判断。

第二个误用是调换顺序:先做 PCA,再标准化。标准化要在 PCA 之前,因为 PCA 的第一要素是中心化,第二步要考虑各特征量纲统一。如果先降维再标准化,标准化作用于已经混合了原始特征的主成分,各主成分之间的尺度关系会被破坏。

第三个误用是把 PCA 和 LDA 混为一谈。PCA 寻找方差最大的方向,LDA 寻找类别可分性最大的方向,数学上 LDA 要对类内散度矩阵和类间散度矩阵做广义特征分解。两者适用的数据形态不同,PCA 可以用于无标签数据,LDA 必须有标签。在分类场景里如果想做监督降维,优先看 LDA 而不是 PCA。

4.4 教学案例中的完整实验流程

一个合格的教案实验流程可以分为四段:先画四个原始特征的散点图矩阵,让学生看到特征之间存在明显的线性相关性;再做 PCA 降维到二维,画出主成分散点图,让学生直观对比前后差别;接着打印特征向量载荷表,让学生把主成分和原特征对应起来;最后掷出一个问题:为什么前两个主成分就能把三个类别基本分开。教学演示里解释方差比和碎石图是必须打印出来的中间结果,不要直接跳到降维完成后的画面。

5. 用主成分分析法的载荷做压缩与业务解释

主成分分析法的应用并不局限于二维可视化,数据压缩是一个直接受益的场景。对于一批人脸图像或商品图片,每张图展开后是一个高维向量,比如 64x64 像素就是 4096 维。用 PCA 对图像矩阵直接拟合并逆变换,相当于只保留前 k 个主成分的重建图像,参数 k 控制压缩率。

from sklearn.datasets import fetch_olivetti_faces faces = fetch_olivetti_faces(shuffle=True, random_state=42) X_faces = faces.data print("原始图像数据形状:", X_faces.shape) k = 32 pca = PCA(n_components=k, whiten=True) X_compressed = pca.fit_transform(X_faces) X_reconstructed = pca.inverse_transform(X_compressed) print(f"压缩后维度: {X_compressed.shape[1]}, 原维度: {X_faces.shape[0]}")

whiten=True会让主成分缩放为方差为 1 的独立分量,这一步对图像重建影响不大,但对后续用主成分做聚类或分类有好处。经验值方面,k 取原维度十分之一左右就能保留人脸的轮廓信息;降到二十分之一时,图像会明显模糊但依然可辨认。这个例子的意义是让学生理解,PCA 找到的低维子空间不是任意丢弃像素,而是保留了像素间最强的协同变化模式。

解释主成分本身是另一个容易被忽略的技巧。以电商用户特征为例,原始字段包括登录次数、浏览时长、加购数、成交金额。如果第一主成分的载荷在四个字段上全部为正且数值接近,那么可以把 PC1 解释为“用户活跃与消费强度”的综合指标;第二主成分若在登录次数上有大正载荷、在成交金额上有大负载荷,则代表“高活跃低转化”和“低活跃高转化”的对比轴。这种解释虽不是严格因果,但在业务场景里能把抽象主成分变成可沟通的维度。如果在业务报告里要用主成分得分做排序或评分,建议对主成分得分做百分位归一化后使用,避免负值在展示上的困惑。主成分分析法能压缩、能可视化、能辅助理解数据结构,但它只认方差,不认业务含义;主成分的业务命名,永远要靠人来完成,这正是使用者的经验所在。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询