数学建模社区-数学中国

标题: 因子分析:数学建模竞赛中的"降维 + 评价"利器 [打印本页]

作者: 2744557306    时间: 2026-8-19 15:31
标题: 因子分析:数学建模竞赛中的"降维 + 评价"利器
因子分析:数学建模竞赛中的"降维 + 评价"利器
写给参加全国大学生数学建模竞赛(CUMCM)的同学 · 基础概念 / 模型公式 / 可视化 / 可运行代码 全干货
一句话定位: 因子分析(Factor Analysis, FA)是一种从一堆高度相关的指标中,提取出少数几个"公共因子"的统计方法。它既能降维去冗余,又能把指标归类成构念,是评价类、聚类类赛题的高频建模工具——但用错一步,结论就会"假了"。本文把算法讲透,并附可直接套用的 Python 流程。


0 l  q6 p9 H$ _目录
. t" h8 t' v6 K: d/ ?! n& S) p3 q
一、为什么竞赛要用因子分析
全国大学生数学建模竞赛中,评价类问题几乎年年出现:给一堆指标(如水质、城市竞争力、上市公司绩效、区域创新能力),让你给对象排名或分类。这类题有四个典型痛点,因子分析正好对症:
⚠️ 先区分两个易混方法: 主成分分析(PCA)只做"最大方差压缩",是综合指标;因子分析额外建模了误差项,目标是解释变量间的相关结构、还原潜在构念。评价建模若想"命名因子",优先 FA;若只需压缩且解释力足够,PCA 也可。
. d6 k  j0 D3 Z3 I' W( x$ q$ j
[td]
. t; T, f- j* j0 J( q" M: y
维度
主成分分析 PCA
因子分析 FA
目标
保留最大方差(线性组合)
解释变量间相关结构(潜在构念)
模型
无误差项,主成分 = 原变量线性组合
含特殊因子 ε,公共因子建模
处理方差
全部方差(含独特方差)
仅"共同方差"
结果命名
难解释(是混合指标)
易命名(是潜在维度)
竞赛适用
纯降维 / 输入压缩
指标归类 / 构念提取 / 评价赋权

' U' W, ]. E' Y1 ?, d4 |  T
二、核心概念
因子分析假设:我们观测到的 $$p$$ 个标准化指标,其实是由少数 $$m$$ 个不可直接观测的公共因子加上每个指标各自的特殊因子共同决定的。
直觉图: 下面这张结构图把"6 个观测指标"通过载荷连到了"2 个潜在因子"。因子分析的本质,就是反过来——从指标的相关关系推断这张隐藏的网络
图1 因子分析结构示意图​F₁公共因子1F₂公共因子2X₁X₂X₃X₄X₅X₆载荷 aᵢⱼ(相关系数,粗细≈大小)7 e9 G0 {' r4 b7 P

9 o# m: y4 H: W) ]
图1 因子分析结构示意图:观测变量经载荷连向潜在公共因子
2 D! _" Y5 Y" C$ s
Snipaste_2026-08-19_15-42-37.jpg " |4 j3 m0 M! J6 ?6 W" S, {- V

8 b' _- V, [7 z/ V# M
三、数学模型与关键公式3.1 基本模型
设标准化后的观测向量 $$\mathbf{X}=(X_1,\dots,X_p)^\top$$,公共因子 $$\mathbf{F}=(F_1,\dots,F_m)^\top$$,特殊因子 $$\boldsymbol{\varepsilon}=(\varepsilon_1,\dots,\varepsilon_p)^\top$$,则
$$
, ^1 T- s7 A9 J3 I! ]; x. RX_i = a_{i1}F_1 + a_{i2}F_2 + \cdots + a_{im}F_m + \varepsilon_i,\qquad i=1,\dots,p$ g" l3 }6 A% I' F5 n( Z# h4 V- V
$$
4 n: T2 C/ O) j& l( p
% ]6 e5 ]' e6 t9 a  I3 }
等价于矩阵形式:
$$9 j; y- b- r" E7 g6 `0 W0 L
\mathbf{X} = \mathbf{\Lambda}\mathbf{F} + \boldsymbol{\varepsilon}6 O5 X+ M  k, B
$$

& Q; L( c; y/ L# @) c5 r4 o4 [
$ ]% I* H, ~% P) G8 r# v
其中 $$\mathbf{\Lambda}$$为 $$p\times m$$ 因子载荷矩阵,$$E[\mathbf{F}]=\mathbf{0},\ \mathrm{Cov}(\mathbf{F})=\mathbf{I}_m$$,$$E[\boldsymbol{\varepsilon}]=\mathbf{0}$$,且$$\mathbf{F}$$与 $$\boldsymbol{\varepsilon}$$ 不相关。
3.2 协方差分解(模型的核心)
由模型可得观测变量的协方差(标准化后即为相关矩阵 $$\mathbf{R}$$):
$$( @( u- h4 z( Q
\mathbf{\Sigma} = \mathrm{Cov}(\mathbf{X}) = \mathbf{\Lambda}\mathbf{\Lambda}^\top + \mathbf{\Psi},\qquad \mathbf{\Psi}=\mathrm{diag}(\psi_1,\dots,\psi_p)4 R5 n3 R3 l6 T) l2 [% M
$$

) U" D! [; }, q! u0 T& f& a
- U4 `1 p1 U; @0 G* A% S7 O: r
$$\mathbf{\Lambda}\mathbf{\Lambda}^\top$$ 是公共因子贡献,$$\mathbf{\Psi}$ $是特殊方差(唯一性)。这正是 FA 与 PCA 的根本区别:FA 显式地把"误差方差"$$\Psi$$ 单独拆了出来。
3.3 公因子方差与方差贡献
公因子方差(共同度):
1 i  A) N/ m0 U1 b共同度(变量 i 的共性方差):\[h_i^2 = \sum_{j=1}^{m} a_{ij}^2 = 1 - \psi_i\]因子 $j$ 的方差贡献:\[V_j = \sum_{i=1}^{p} a_{ij}^2\]累计方差贡献率:\[\frac{\sum_{j=1}^{m} V_j}{\sum_{i=1}^{p} h_i^2} \approx \frac{\sum_{j=1}^{m} V_j}{p}\]
实际选因子时,常要求累计方差贡献率 ≥ 80% 且每个指标的共同度 $$h_i^2$$ 不宜过低(一般 ≥ 0.4)。
3.4 因子旋转:让因子"可命名"
初始载荷往往分散、难解释。通过正交旋转(保持因子不相关)让每个变量只在少数因子上有高载荷。最常用的是 Varimax(方差最大化旋转),其目标是最大化各列载荷平方的方差:
$$
5 V* f  q) u* l, J  w% {5 c\max \sum_{j=1}^{m} \left[ \frac{1}{p}\sum_{i=1}^{p} (\tilde a_{ij})^4 - \left(\frac{1}{p}\sum_{i=1}^{p} (\tilde a_{ij})^2\right)^2 \right]
( J3 ?5 a1 L, X$ P5 G! S" P1 n$$

+ L# r7 y2 c* H" |5 ]: D
; H3 G! Z6 z' u7 J( q1 a+ ~3 x. B& T
旋转不改变模型拟合优度与共同度,只改变载荷分布,方便命名(例如把 F1 命名为"规模因子"、F2 命名为"效率因子")。
3.5 因子得分与综合得分
对每个样本估计其因子得分(回归法):
$$
3 I7 f( P- Q& t* L) ^3 p\hat{\mathbf{F}} = \big(\mathbf{\Lambda}^\top\mathbf{\Psi}^{-1}\mathbf{\Lambda}\big)^{-1}\mathbf{\Lambda}^\top\mathbf{\Psi}^{-1}\mathbf{X}
5 [; O& O  [( X( W( {9 w2 F3 k$$
+ S6 s7 a; @2 G7 V; X) H1 w

9 _6 N! X; E& B- i! v" X. D
用各因子方差贡献作权重,得到综合得分(排名依据):
$$& }* {/ e$ T" {! M4 R4 G! a
S_k = \sum_{j=1}^{m} w_j\,\hat F_{kj}, \qquad w_j = \frac{V_j}{\sum_{j=1}^{m} V_j}; _1 r. Z  q* ?0 Y6 f
$$

: u& r2 Y7 D) M. Q& T/ |) K. i" ?6 I' z( {" s
3.6 做之前必须先做的两个检验
不是任何数据都适合因子分析。先过两关:
Bartlett 球形检验: 原假设"相关矩阵 = 单位阵(变量独立)"。检验统计量
$$
6 y/ T, S; k7 [5 f6 B\chi^2 = -\left(n-1-\frac{2p+5}{6}\right)\ln|\mathbf{R}|, z5 P9 h: G: W" y* D3 `
$$

9 W8 l0 p3 w6 k9 G* b& L; l# V; ~
0 G! j# J$ S7 {* E* r' p
要求 $p$ 值 < 0.05,才拒绝原假设、适合做 FA。
KMO 取样适切性量数:
$$5 n! M% q3 e/ E! y* c  s
\mathrm{KMO} = \dfrac{\sum_{i\neq j} r_{ij}^2}{\sum_{i\neq j} r_{ij}^2 + \sum_{i\neq j} p_{ij}^2}5 v. n$ A1 ]! k$ {& I) _  v
$$

, W7 h) [/ s4 \* V3 i; y. h/ |8 [. N# |- s
r{ij}为相关系数,p{ij}为偏相关系数。KMO ≥ 0.6 可用,≥ 0.8 很好。


3 w9 o, K. Z3 z" h四、标准算法流程(八步)
6 d* \! J- t) b  c
五、四张可视化图表图2 碎石图(Scree Plot)—— 决定保留几个因子
特征值按从大到小排列,落在"陡坡转平台"的拐点之后、且低于红线(特征值=1)的因子不再保留。本例保留 F1、F2。
​因子序号特征值0123特征值 = 1保留F1(2.61)F2(1.74)F3(0.92)F4(0.41)F5(0.19)F6(0.13)9 z8 A( H3 z) W8 \  E6 x
0 v! Z0 Z# i, H
图2 碎石图:前两个因子特征值 > 1,构成拐点,予以保留
. k7 Y' z' X4 k5 W3 K4 U
Snipaste_2026-08-19_15-44-04.jpg
' W" @6 _! w) a& j! h! Q图3 因子载荷热图(旋转后)—— 看指标归到哪个因子
颜色越深表示载荷绝对值越大。理想旋转结果:每列出现少数高载荷(深色),其余接近 0,从而清晰命名。
​F₁(规模因子)F₂(效率因子)指标X₁X₂X₃X₄X₅X₆0.860.810.150.080.790.120.100.220.880.83−0.180.77强正强正弱负近08 L2 y/ N& j' D! K
Snipaste_2026-08-19_15-44-46.jpg
  T& [& B% B- \* @8 h
图3 旋转后载荷热图:X₁/X₂/X₅ 归 F₁,X₃/X₄/X₆ 归 F₂,命名清晰
图4 因子得分散点图(四象限)—— 样本分类
把每个样本的两个因子得分画成散点,可直观做聚类/定位:右上"双高"、左上"效率型"、右下"规模型"、左下"双低"。
​F₁ 得分 →F₂ 得分 ↑双高型效率型规模型双低型ABCDEFGH# n1 v% e1 I" F' X8 D

; O3 ^: D9 {. X: v+ [) e
图4 因子得分散点图:按双因子得分对样本做四象限定位与聚类

5 d( `6 b/ Z# v Snipaste_2026-08-19_15-44-52.jpg
4 P) \/ A$ T9 R# Y

, i: u2 \4 Q3 b! B" t& r+ O& C六、Python 实战代码
推荐使用 factor_analyzer 库(专为因子分析设计,自动给出 KMO、Bartlett、载荷、方差贡献)。pip
  1. import pandas as pd
    , T& |& U: [" A' \  n, Q# k% e
  2. import numpy as np2 V8 j6 @3 r' G! j1 D4 H
  3. from factor_analyzer import FactorAnalyzer
    - R, ^4 r5 B: j* p8 s
  4. from factor_analyzer.factor_analyzer import calculate_kmo, calculate_bartlett_sphericity
    + v5 v/ G8 f# m; [, X" j
  5.   C) u9 O6 {6 _) V4 Y
  6. # 1) 读取数据(行=样本,列=指标),并 Z-score 标准化' y3 C6 S* z9 z, [
  7. df = pd.read_excel('indicators.xlsx'); g9 u) r! j) ]/ I% P) r1 I; u
  8. X  = (df - df.mean()) / df.std()
    $ a1 d( P) F: ~/ u) B( g# l
  9. ; j) o0 L( Q8 K" F( a# ]
  10. # 2) 适用性检验
    + |( \, M9 p( b9 x0 f
  11. chi2, p_value = calculate_bartlett_sphericity(X)
    . `* m. Q$ j; L# \5 Y
  12. kmo_all, kmo_model = calculate_kmo(X)
    + ]. [8 Y* X6 Z# s& o' E8 l9 D
  13. print(f'Bartlett p={p_value:.3g}  KMO={kmo_model:.3f}')   # 需 p<0.05 且 KMO≥0.67 G* k5 @0 U9 N; H

  14. - C; Y( C, \# H9 v! Y# L) w) G+ ^+ y
  15. # 3) 先看所有特征值,确定因子数 m(特征值>1 准则)
    7 Z, B* s# \; ^7 [# l* n
  16. fa0 = FactorAnalyzer(n_factors=df.shape[1], rotation=None, method='principal')
    ; \& F+ J, ^" E" L, y
  17. fa0.fit(X)7 n, z. B3 H. t
  18. ev, _ = fa0.get_eigenvalues()
    . H9 H# c. i$ F' ^! q. i
  19. print(pd.Series(ev, name='eigenvalue').round(3))
    3 |/ H: \4 t  y8 i/ |( I! ~; f
  20. ; X/ C  {) l& [$ |; `
  21. # 4) 提取 m 个因子 + Varimax 旋转9 m! h5 b7 G# P; a. ^
  22. m = 2
    : \% i; J0 X) X5 t+ D
  23. fa = FactorAnalyzer(n_factors=m, rotation='varimax', method='principal')* e1 }+ U3 p9 V5 g+ w! v! c" [
  24. fa.fit(X)
    ) [1 f1 u% I0 w: C6 H

  25. 1 `8 Q( {6 t2 y! s
  26. loadings = pd.DataFrame(fa.loadings_, index=df.columns,
    ( z2 y6 A# {6 r" J1 [
  27.                         columns=[f'F{j+1}' for j in range(m)])4 X9 ~2 s$ w2 u" Y
  28. print(loadings.round(3))
    + O4 v: B6 m2 Q6 X, i
  29. $ c9 g7 _, `# ^( S" S7 I
  30. # 5) 因子得分 → 方差贡献加权得到综合得分
    " h9 ?7 n  e! f! o  ]* {
  31. scores   = fa.transform(X)                         # 形状 (n, m)) |- a6 g" [) g& G( F
  32. variance = fa.get_factor_variance()[0]            # 各因子方差贡献
    7 W8 Y' G9 r  f8 D) ]8 m
  33. weights  = variance / variance.sum()
    2 u6 c3 U0 D/ T  T# S
  34. composite = (scores * weights).sum(axis=1)
    ! S2 o. n" K1 M

  35. ; e* ~( X' P' _2 t7 v! Z  P
  36. result = df.copy()( N" f7 b* w2 Z4 i
  37. result[[f'F{j+1}' for j in range(m)]] = scores
    - e- L* C* H" s  x
  38. result['综合得分'] = composite& N7 X1 @5 J) B, y2 l& q
  39. result['排名'] = composite.rank(ascending=False).astype(int)
    % |9 D# ~3 ^6 ~! v/ Z0 |. u' j, G
  40. print(result.sort_values('排名').head(10))
复制代码
⚠️ 小技巧: 若数据量较小(n < 50 或 n < 5p),优先用 method='principal'(主成分法)而非极大似然法,后者对小样本不稳定。竞赛数据常见样本数有限,主成分法更稳健。

0 [# v+ s, A! v
七、竞赛案例:城市创新能力评价(简化)
假设有 6 个指标、8 个城市,指标为:R&D 经费投入(X₁)、每万人专利数(X₂)、高新技术企业数(X₃)、技术市场成交额(X₄)、产业结构高级化(X₅)、创新环境指数(X₆)。
这一套路在评阅中很"稳":每一步都有统计依据(KMO/Bartlett 证明能做、特征值证明取几个、载荷证明怎么命名、方差贡献证明权重怎么来),比"我拍脑袋定了 5 个一级指标"强太多。


( T' P  B/ E4 O9 v+ K八、常见误区与提分技巧[td]
2 v( q- Y7 F5 h% m
误区
正确做法
跳过 KMO / Bartlett 直接做
先检验,不适配就换方法(如 PCA 或 TOPSIS)
指标方向不统一就标准化
成本类、污染类指标先"正向化",否则因子含义反了
只看特征值>1 定因子数
结合碎石图拐点 + 累计贡献率 + 能否命名,三者互相印证
不旋转,载荷难解释
默认 Varimax;如需因子相关可用 Promax(斜交)
用因子得分直接排名但不写权重来源
明确写出 $w_j=V_j/\sum V_j$,说明客观赋权
共同度过低仍保留该指标
$h_i^2$<0.4 的指标考虑剔除或说明信息损失

" F( A% o, b+ w$ L
九、赛场自查清单
3 [5 }: @( J' f0 m  G( b
本文公式与流程均依据多元统计分析标准教材(如 Johnson & Wichern《Applied Multivariate Statistical Analysis》、何晓群《多元统计分析》),可直接用于数学建模竞赛论文方法章节。图表为说明性示例数据,实战请替换为赛题真实数据。
— 写给认真备赛的你 · 祝建模顺利 —
6 \. _2 P' B6 S# }9 ^

$ V3 a: D8 J6 G" ?6 i4 @( A4 o& g
4 d6 I7 ?8 m$ _+ |% F

3 s: L" C' f) c, x" r) b2 w
+ @' g; v* z+ s5 _) @+ N) Y. J$ y  f/ @/ W* q" c# s5 n2 a! U

$ V& L, q8 h3 z' u
- x% B* f4 e0 g& k
; s+ F0 f! M6 f9 Z0 `1 R( V  P5 S# D( `4 u8 [
: e9 T; q+ \# ^) B$ n* |7 h- o





欢迎光临 数学建模社区-数学中国 (http://www.madio.net/) Powered by Discuz! X2.5