主成分分析与因子分析:从数学原理到Python落地 简介主成分分析与因子分析教学PPT面向统计学入门至进阶学习者、社科经管等专业师生及需要做数据降维的科研人员系统讲解两类多维数据分析方法的原理与实现。内容从数学建模出发覆盖协方差矩阵、特征值分解、主成分个数选取、因子旋转与SPSS操作步骤并结合上衣尺寸、儿童身高体重、企业经济效益评估等实例帮助理解。全包为1个PPT文件大小仅340KB便于快速浏览与复习。已有71人学习。通过这套教学材料读者可掌握主成分分析与因子分析的异同、适用场景以及利用SPSS输出载荷矩阵与贡献率并解读结果的能力适合作为课堂教案或自学辅助资料。1. 主成分与因子分析不只是降维更是找隐形变量做特征工程时最常被问到的一句话是“你留了这么多特征它们之间真的没重复吗”主成分分析PCA和因子分析FA就是回答这类问题的两把尺子。PCA 把一组线性相关的特征重新组合成互相独立的综合维度并按方差大小排序因子分析更进一步直接假设这些可观测特征背后存在少数不可直接测量的潜变量比如“满意度”“活跃度”“风险偏好”再用观测数据去估计它们。如果你手里有几十列的问卷或运营指标又需要在讲解时说清“为什么这些题能合成一个维度”“为什么建模前要砍掉一半特征”这套分析就是绕不开的底层逻辑。下面按“数学原理到 Python 实现、再到方法选型和教案呈现”的顺序展开中间给出可直接运行的代码和参数说明适合数据分析师、算法工程师以及需要做内部培训的同学。2. 先理解主成分与因子分析的数学内核协方差、特征值与方差解释率主成分分析与因子分析的共用起点是协方差矩阵。PCA 的出发点很直观在所有可能的线性组合里找到一条方向让样本投影到这条方向后方差最大。方差越大这个方向保留的原始差异越多多个这样的方向保持正交就形成了主成分。从矩阵视角看这等价于对协方差矩阵做特征值分解特征值大小对应主成分方差特征向量对应载荷系数。因子分析的结构稍有不同它把每个原始变量拆成公共因子与特殊因子的线性组合目标从“最大化总体方差”变成了“解释变量间的相关结构”但矩阵运算仍旧落在协方差或相关矩阵上。2.1 从协方差矩阵到特征值分解为什么挑最大特征值的方向给定一个已经中心化的数据矩阵 Xn 个样本p 个特征协方差矩阵 C 刻画了特征两两之间的协同变化。我们希望找到一个单位向量 w使得投影后的方差 w^T C w 最大。用拉格朗日乘子法求解最优点 w 恰好满足特征方程 C w lambda w。也就是说w 是 C 的特征向量对应的特征值 lambda 就是该方向的方差。特征值越大该方向承载的方差越大信息量越多。前 k 个最大特征值对应的特征向量拼成矩阵左乘标准化数据就得到 k 维主成分得分。这里有一个新手容易忽略的点协方差矩阵要求特征在同一个量纲下才可比。身高和收入放在一起方差几乎被收入主导必须先标准化。标准化之后协方差矩阵退化为相关系数矩阵这也是主成分与因子分析在实际项目里的共同前提。因子分析虽然没有像 PCA 那样直接号称“找最大方差方向”但公共因子同样在解释相关矩阵的结构因此基于相关矩阵计算仍然是默认动作。2.2 用 Python 手写一遍 PCA标准化、协方差、特征向量与得分为了避免被 sklearn 的封装挡住细节先手工实现一遍 PCA。数据量不大时这种写法速度足够还能帮助你确认每一步对结果的影响import numpy as np # 模拟数据5个样本3个特征 X np.array([[2.5, 2.4, 1.3], [0.5, 0.7, 1.9], [2.2, 2.9, 2.4], [1.9, 2.2, 3.1], [3.1, 3.0, 2.8]]) # 1. 标准化每个特征减去均值除以标准差 X_std (X - X.mean(axis0)) / X.std(axis0) # 2. 求相关系数矩阵等价于标准化后的协方差矩阵 corr_mat np.corrcoef(X_std, rowvarFalse) # 3. 特征值分解eigh 专用于对称矩阵数值更稳定 eig_vals, eig_vecs np.linalg.eigh(corr_mat) # 4. 特征值从大到小排序 idx np.argsort(eig_vals)[::-1] eig_vals eig_vals[idx] eig_vecs eig_vecs[:, idx] # 5. 取前2个主成分计算得分 scores X_std eig_vecs[:, :2] # 6. 解释方差占比 var_ratio eig_vals / eig_vals.sum() print(特征值:, eig_vals) print(解释方差占比:, var_ratio) print(主成分得分前5行:\n, scores)这段代码覆盖了 PCA 的完整流程标准化、相关系数矩阵、特征分解、降维投影。eigh比eig更快也避免对称矩阵计算出微小虚部。排序后取前两个特征向量变换得到的就是样本在低维空间的坐标。var_ratio直接回答“第一个主成分解释了多少信息”这是后文选主成分个数的核心依据。手工写法在数据量过万、特征上百时会变慢实际生产环境通常改用奇异值分解或随机化 SVD这也是 sklearn 中svd_solver参数存在的意义。2.2.1 标准化是前提不标准化等于在给量纲发奖上面对数据做了标准化这不是可选操作。如果不做量纲差异会直接干扰特征向量排序。一组数据里年龄以“岁”为单位、收入以“万元”为单位、点击次数以“百次”为单位收入列天然方差更大特征值分解会优先照顾方差大的方向结果就是主成分被少数量纲大的特征绑架。标准化之后每个特征方差都为 1处于同一起点。因子分析里同样如此因子载荷矩阵的实际含义要求变量可比较否则载荷大小不具备解释意义。2.3 方差解释率与碎石图到底保留几个主成分保留多少个主成分没有绝对标准但有三个常用经验特征值大于 1 的 Kaiser 准则、累计方差贡献率达到 80%、碎石图中找肘部拐点。三者经常配合使用。假设前面例子的输出如下表主成分特征值单个方差解释率累计方差解释率PC11.8260.7%60.7%PC20.8628.7%89.4%PC30.3210.6%100%按累计 80% 的标准前两个主成分解释 89.4% 的信息于是取 k2。碎石图的做法是按特征值从大到小画折线找到下降趋势由陡变缓的位置保留拐点之前的成分。实际项目里数据噪声通常让特征值缓慢下降所以拐点经常在累计贡献率 70% 到 90% 之间出现。我的建议是不要只盯一个阈值把特征值、累计贡献率和业务可解释性放在一起讨论例如用主成分表示“活跃度”和“消费力”都说得通时保留数量才有说服力。3. 用 sklearn 和 factor_analyzer 落地主成分与因子分析参数这样设看懂原理之后可以直接借助成熟库落地。PCA 用 scikit-learn因子分析用 factor_analyzer后者可以通过pip install factor-analyzer安装。下面分别说明核心参数和实际排错经验。3.1 sklearn 的 PCA 核心参数n_components、whiten、svd_solver先看一份典型的 PCA 调用代码import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.decomposition import PCA df pd.read_csv(data.csv) X df.select_dtypes(include[number]).dropna() # 标准化PCA 前必须做否则量纲影响主成分方向 scaler StandardScaler() X_scaled scaler.fit_transform(X) # n_components0.9 表示自动保留至少解释90%方差的主成分数量 pca PCA(n_components0.9, svd_solverfull, whitenFalse) X_pca pca.fit_transform(X_scaled) print(解释方差比:, pca.explained_variance_ratio_) print(累计解释方差比:, pca.explained_variance_ratio_.cumsum()) print(特征值:, pca.explained_variance_) print(载荷矩阵形状:, pca.components_.shape)参数说明分三层看。n_components可以传 float 或 int传0.9表示自动选择能让累计方差解释率超过 90% 的最少成分数传3则强制保留 3 个主成分。svd_solver有auto、full、arpack、randomized四个选项数据量小且要精确求解释方差比时用full样本量大、特征也多的建模场景用randomized更快但结果略有随机性。whiten默认 False或为 True 时每个主成分的方差会被归一化到 1适合后面接距离类模型但会让主成分失去原始方差语义做解释分析不建议开。pca.components_是载荷矩阵行数等于保留的主成分数列数等于原始特征数每一行代表一个主成分在原特征方向上的投影系数。注意它不等于因子分析里的载荷因为 PCA 不引入潜变量假设主成分得分是原始特征的精确线性组合而因子分析的得分只是一个估计。3.2 因子分析的核心参数rotation、n_factors、threshold因子分析使用factor_analyzer.FactorAnalyzer代码比 sklearn 更直观from factor_analyzer import FactorAnalyzer from factor_analyzer.factor_analyzer import calculate_bartlett_sphericity # 抽取3个公共因子使用方差最大正交旋转 fa FactorAnalyzer(n_factors3, rotationvarimax, methodprincipal) fa.fit(X_scaled) # 载荷矩阵threshold 控制打印时只显示绝对值足够大的系数 print(fa.loadings_.round(3)) # 公因子方差每个原始特征被公共因子解释的比例 communalities fa.get_communalities() print(公因子方差:, communalities) # 因子方差、方差占比和累计占比 var_stats fa.get_factor_variance() print(因子方差统计:, var_stats) # Bartlett 球形检验p0.05 才适合做因子分析 chi2, p_value calculate_bartlett_sphericity(X_scaled) print(Bartlett p值:, p_value)n_factors是公共因子数量不直接等于主成分数。建议先用特征值大于 1 的个数粗定范围再对比不同因子数下的公因子方差和载荷解释性。rotation的常用值有varimax正交旋转、因子不相关、解释简单和promax斜交旋转、允许因子间相关。methodprincipal使用主因子法适用面广methodml使用极大似然估计数据接近正态分布时拟合质量更高但迭代不收敛的情况也更常见。get_factor_variance()的输出和 PCA 的解释方差比类似但注意旋转会让方差贡献在因子间重新分配因此不要直接说“第一个因子最重要”这种结论只在未旋转结果里可靠。3.3 主成分载荷矩阵与公因子方差从“数学解”到“业务解释”无论 PCA 还是 FA最终都要解释每个维度代表什么。载荷矩阵是核心材料。下面是一份示意表格原始特征PC1 / 因子1PC2 / 因子2公因子方差访问时长0.820.120.69浏览页数0.760.200.62消费金额0.150.910.85下单次数0.220.880.82载荷值可以被看作原始特征与主成分或公共因子之间的相关系数。绝对值越接近 1说明该特征在这个维度上的承载越强。公因子方差是每行载荷的平方和表示该特征被当前维度集合解释的比例。例如“访问时长”的公因子方差是 0.69意味着约 69% 的方差由这两个维度解释剩余 31% 属于特殊因子与噪声。如果在 PCA 中做同样解释需要换一个名称PCA 里对应的是“每个特征被前 k 个主成分重构的精度”本质是低秩近似的拟合优度。放到 PPT 或教案里这张表配上载荷热力图会比单纯贴特征值列表直观得多。4. 主成分与因子分析的关键区别选错方法结论可能翻车很多人在拿到数据后习惯性调PCA()却发现论文里写着“旋转后因子载荷”于是怀疑自己是否用错了工具。主成分与因子分析确实既有血缘又有分野。选错的风险在于PCA 把误差和特殊波动也并入主成分后续回归可能把噪声当信号因子分析若前提假设不成立则可能因子数量举棋不定载荷解释牵强甚至无法收敛。4.1 目标和假设不同方差最大化还是协方差结构解释PCA 的目标是让投影后总体方差最大不关心数据背后有没有不可观测的真实维度因此适合降维、去相关和可视化。因子分析的目标是找到能解释变量相关结构的潜变量适合量表验证、画像构建这类需要“命名维度”的场景。矩阵分解上区分更清晰PCA 是对协方差矩阵做精确的谱分解前 k 个特征向量就能给出最优低秩近似因子分析则把每个变量拆成公共因子、特殊因子和误差分解的对象是变量间的相关结构而不是完整方差。对比维度主成分分析 (PCA)因子分析 (FA)核心目标最大化整体方差解释变量间的协方差/相关结构是否假设潜变量否是是否需要旋转通常不需要通常需要主要输出主成分得分、载荷因子得分、旋转后载荷、公因子方差典型场景高维特征压缩、可视化问卷效度验证、潜变量建模这张对比表可以直接放进 PPT 作为一页。实在拿不准时问自己是想减少特征数量、压缩数据还是想告诉别人“这 20 道题背后其实是 3 个维度”前者选 PCA后者选 FA。4.2 旋转方法选择正交旋转与斜交旋转的边界因子分析里的旋转是为了让载荷矩阵结构更简单让每列尽量只在少数变量上有较大载荷。正交旋转包括 varimax、quartimax、equamax旋转后因子之间不相关斜交旋转包括 promax、oblimin允许因子之间存在相关。正交旋转的优点是解释直接、便于计算因子得分后做回归缺点是现实中的潜变量往往并不完全独立强制正交可能扭曲载荷。常见做法是两类旋转都跑一遍如果斜交旋转后的因子相关矩阵里系数绝对值都低于 0.3就选择正交旋转如果明显超过 0.3说明应该接受因子间的相关性。判断因子相关矩阵的代码很短import pandas as pd from factor_analyzer import FactorAnalyzer fa_oblique FactorAnalyzer(n_factors3, rotationpromax) fa_oblique.fit(X_scaled) corr_factors fa_oblique.get_factor_correlation() print(pd.DataFrame(corr_factors))输出是一个 3x3 矩阵对角线是 1非对角元素表示因子两两相关程度。如果对角外的值都很接近 0因子之间近似独立旋转方式影响很小如果出现大于 0.3 的系数说明潜变量本身存在关联PPT 里讲“为什么用斜交旋转”时给出这页矩阵就是最直接的证据。要注意旋转会改变载荷分配但不会改变模型的整体拟合程度因此不要指望靠旋转提高公因子方差总和。4.3 筛选指标特征值、累计贡献率与 KMO 检验怎么用做因子分析前有一项 PCA 中通常不做的体检KMO 抽样充分性检验和 Bartlett 球形检验。KMO 低于 0.6 时变量间的偏相关性太弱因子分析很难提取出稳定的公共因子。代码直接调用factor_analyzer的工具即可from factor_analyzer import FactorAnalyzer from factor_analyzer.factor_analyzer import calculate_kmo kmo_all, kmo_model calculate_kmo(X_scaled) print(KMO , kmo_model)kmo_model取值范围 0 到 1大于 0.7 才建议继续因子分析0.8 以上视为良好。Bartlett 球形检验检查相关矩阵是否为单元矩阵p 值小于 0.05 说明变量间存在显著相关性适合做因子提取。特征值大于 1 的因子数量可以作为初始候选再配合累计方差贡献率和碎石图共同决定最终数量。这些指标在 PCA 里不是必需因为 PCA 不依赖统计假设但如果要在报告或教案中写“适合做因子分析”这两个检验是必出示的证据。实际操作中KMO 低通常意味着某些变量和其他变量完全无关删除后重新计算往往能显著改善。5. 把结果做成一份能讲清楚的一份教案验证与可视化5.1 用双标图biplot同时展示样本与载荷理解是内隐的讲给别人就要靠图。双标图是 PCA 最直观的可视化横轴 PC1、纵轴 PC2散点是样本得分红色箭头是原始特征在主成分平面上的投影方向。箭头方向相近说明特征正相关夹角接近 90 度说明相关性弱箭头越长说明该特征在这个主成分平面上的贡献越大。import matplotlib.pyplot as plt import numpy as np plt.figure(figsize(8, 6)) plt.scatter(X_pca[:, 0], X_pca[:, 1], alpha0.6) # 载荷向量画成箭头坐标乘以3是为了和样本散点在同一可视范围 for i, (vec_x, vec_y) in enumerate(pca.components_.T): plt.arrow(0, 0, vec_x * 3, vec_y * 3, colorred, alpha0.5, head_width0.08) plt.text(vec_x * 3.1, vec_y * 3.1, ffeature_{i}, colorred) plt.xlabel(PC1) plt.ylabel(PC2) plt.grid(True) plt.show()箭头长度乘 3 取决于数据本身的坐标尺度可以按图形效果调整。讲解时要说清楚三点散点位置是降维近似不是原始空间真实距离箭头角度反映载荷正负和强弱箭头和散点之间没有距离可比性。许多听众误解双标图里的“靠近”是原始特征相关性的直接视觉化实际上需要看夹角而不是距离。5.2 验证降维质量重构误差与累计方差曲线很多教案讲完特征值就结束我通常会补一张重构误差图。原理是用前 k 个主成分投影回原空间再和标准化后的原始数据比较重构误差越小说明信息损失越少。这比单纯看累计贡献率更贴近下游建模的真实需求。def reconstruction_error(X_scaled, k): pca_k PCA(n_componentsk) X_k pca_k.fit_transform(X_scaled) X_reconstructed pca_k.inverse_transform(X_k) return np.mean((X_reconstructed - X_scaled) ** 2) ks range(1, X_scaled.shape[1] 1) errors [reconstruction_error(X_scaled, k) for k in ks] plt.plot(ks, errors, markero) plt.xlabel(保留主成分数) plt.ylabel(重构误差MSE) plt.show()误差曲线出现明显拐点或下降趋势趋缓的位置往往比拍脑袋定 80% 更可靠。把这张图和累计方差曲线并排放入 PPT听众能看到两条曲线在同一位置转折比听你念出“我们保留前三个因子”更有说服力。如果重构误差在高维度下依然很大说明前几个主成分未必能支撑你想要的压缩目标这时可能是数据本身信噪比低或者标准化方式不适合原始特征分布。5.3 教案结构设计的 4 个关键页把前面内容组织成教学材料我一般按四页推进。第一页放场景和反直觉结论例如“20 个指标其实只要 4 个维度就能解释 85% 的信息”直接抓住听众。第二页放数学内核只保留相关系数矩阵、特征值分解和方差解释率三个公式再附一张手工 PCA 的核心代码截图。第三页放代码和参数对比表把 PCA 的n_components、svd_solver、whiten与因子分析的n_factors、rotation、method并列强调每个参数对应的业务含义。第四页放案例与陷阱用一份真实数据的 KMO 检验结果、旋转前后载荷差异和因子相关矩阵收尾。选因子个数时不要只写结论建议把特征值表和累计贡献率折线图并排再基于“特征值大于 1 且累计贡献率超过 80%”两个条件圈出建议区间。这样观众能看到判断依据而不是听你念一个神秘数字。课堂上如果时间足够可以在现场调一次n_factors展示因子数从 2 变成 5 之后公因子方差的变化这个动态过程比任何静态截图都能说明“因子分析是一种建模选择而非唯一答案”。本文还有配套的精品资源点击获取