主成分分析评价法(PCA)
“主成分分析的核心思想是降维——用少数几个综合指标代替原来众多的相关指标,同时尽可能多地保留原始数据的信息。” —— Karl Pearson, 1901
基本原理
什么是主成分分析
主成分分析(Principal Component Analysis, PCA)是一种经典的多元统计分析方法,其核心目标是降维。在综合评价问题中,我们常常面对大量相关性较强的评价指标。这些指标之间的重叠信息不仅增加了计算复杂度,还可能导致评价结果失真。PCA通过线性变换,将原始的多个相关指标转化为少数几个互不相关的综合指标(即主成分),从而实现降维与信息浓缩。
方差最大化原则
PCA的数学本质是寻找一组新的正交坐标系,使得数据在新坐标轴上的投影方差最大。具体而言:
- 第一主成分:在所有线性组合中,选取使方差最大的方向,即数据信息量最大的方向
- 第二主成分:在与第一主成分正交(不相关)的约束下,选取方差次大的方向
- 第 \(k\) 主成分:在与前 \(k-1\) 个主成分都正交的约束下,选取方差最大的方向
通过这种方式,前几个主成分通常能够解释原始数据总方差的绑大部分(如85%以上),从而实现“用少量变量概括大部分信息“的目标。
与评价问题的结合
在综合评价中,PCA的优势在于:
- 客观赋权:主成分的权重由数据本身的方差结构决定,无需人为设定
- 消除多重共线性:主成分之间互不相关,避免了指标间信息重叠的干扰
- 降维简化:将高维评价问题转化为低维问题,便于排序与可视化
- 信息量可度量:通过累积贡献率可以量化保留了多少原始信息
数学基础
协方差矩阵
设有 \(n\) 个评价对象,每个对象有 \(p\) 个评价指标,构成数据矩阵 \(X_{n \times p}\)。对数据进行标准化后,协方差矩阵为:
\[ \Sigma = \frac{1}{n-1} X^T X \]
其中 \(\Sigma\) 是一个 \(p \times p\) 的对称正定矩阵,其对角线元素为各指标的方差,非对角线元素为指标间的协方差。当数据已标准化时,协方差矩阵即为相关系数矩阵 \(R\):
\[ R = \begin{pmatrix} 1 & r_{12} & \cdots & r_{1p} \\ r_{21} & 1 & \cdots & r_{2p} \\ \vdots & \vdots & \ddots & \vdots \\ r_{p1} & r_{p2} & \cdots & 1 \end{pmatrix} \]
特征值与特征向量
对协方差矩阵(或相关系数矩阵)进行特征值分解:
\[ \Sigma \mathbf{u}_i = \lambda_i \mathbf{u}_i, \quad i = 1, 2, \ldots, p \]
其中:
- \(\lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_p \geq 0\) 为特征值,表示对应主成分的方差大小
- \(\mathbf{u}i = (u{1i}, u_{2i}, \ldots, u_{pi})^T\) 为对应的特征向量(单位化),即主成分的系数向量
第 \(i\) 个主成分表示为:
\[ F_i = u_{1i} Z_1 + u_{2i} Z_2 + \cdots + u_{pi} Z_p \]
其中 \(Z_1, Z_2, \ldots, Z_p\) 为标准化后的原始变量。
贡献率与累积贡献率
第 \(i\) 个主成分的方差贡献率为:
\[ \eta_i = \frac{\lambda_i}{\sum_{k=1}^{p} \lambda_k} \]
前 \(m\) 个主成分的累积贡献率为:
\[ \sum_{i=1}^{m} \eta_i = \frac{\sum_{i=1}^{m} \lambda_i}{\sum_{k=1}^{p} \lambda_k} \]
一般要求累积贡献率达到 85% 以上,此时可认为前 \(m\) 个主成分已经包含了原始数据的绑大部分信息。
计算步骤
PCA综合评价的完整计算流程如下:
第一步:数据标准化
对原始数据矩阵 \(X = (x_{ij})_{n \times p}\) 进行Z-score标准化:
\[ z_{ij} = \frac{x_{ij} - \bar{x}_j}{s_j} \]
其中 \(\bar{x}j = \frac{1}{n}\sum{i=1}^{n} x_{ij}\) 为第 \(j\) 个指标的均值,\(s_j = \sqrt{\frac{1}{n-1}\sum_{i=1}^{n}(x_{ij} - \bar{x}_j)^2}\) 为标准差。
标准化的目的是消除量纲差异,使各指标具有可比性。
第二步:计算相关系数矩阵
基于标准化数据计算相关系数矩阵 \(R\):
\[ r_{jk} = \frac{1}{n-1} \sum_{i=1}^{n} z_{ij} z_{ik}, \quad j,k = 1, 2, \ldots, p \]
第三步:特征值分解
求解特征方程:
\[ |R - \lambda I| = 0 \]
得到特征值 \(\lambda_1 \geq \lambda_2 \geq \cdots \geq \lambda_p\) 及其对应的单位特征向量 \(\mathbf{u}_1, \mathbf{u}_2, \ldots, \mathbf{u}_p\)。
第四步:确定主成分个数
根据累积贡献率准则,选取前 \(m\) 个主成分,使得:
\[ \frac{\sum_{i=1}^{m} \lambda_i}{\sum_{k=1}^{p} \lambda_k} \geq 85% \]
也可结合碎石图(Scree Plot)辅助判断,选取“肘部“位置之前的主成分。
第五步:计算主成分得分
各评价对象在第 \(i\) 个主成分上的得分为:
\[ F_i = Z \mathbf{u}_i \]
第六步:计算综合评价得分
以各主成分的方差贡献率为权重,计算综合得分:
\[ F = \sum_{i=1}^{m} \frac{\lambda_i}{\sum_{k=1}^{m} \lambda_k} F_i \]
根据综合得分 \(F\) 的大小,对评价对象进行排序。
实际案例分析
案例背景:城市经济发展水平综合评价
假设我们需要对8个城市的经济发展水平进行综合评价,选取以下6个指标:
| 指标 | 含义 | 单位 |
|---|---|---|
| \(X_1\) | 人均GDP | 万元 |
| \(X_2\) | 城镇居民人均可支配收入 | 万元 |
| \(X_3\) | 第三产业占比 | % |
| \(X_4\) | 固定资产投资增速 | % |
| \(X_5\) | 社会消费品零售总额 | 亿元 |
| \(X_6\) | 进出口总额 | 亿元 |
原始数据如下:
| 城市 | \(X_1\) | \(X_2\) | \(X_3\) | \(X_4\) | \(X_5\) | \(X_6\) |
|---|---|---|---|---|---|---|
| A | 12.5 | 5.8 | 62.3 | 8.2 | 4500 | 3200 |
| B | 10.8 | 5.2 | 55.6 | 10.5 | 3800 | 2500 |
| C | 15.2 | 6.5 | 68.1 | 6.8 | 5200 | 4100 |
| D | 8.6 | 4.5 | 48.2 | 12.3 | 2900 | 1800 |
| E | 11.3 | 5.4 | 58.9 | 9.1 | 4100 | 2800 |
| F | 14.1 | 6.2 | 65.7 | 7.5 | 4900 | 3800 |
| G | 9.5 | 4.8 | 51.4 | 11.6 | 3200 | 2100 |
| H | 13.6 | 6.0 | 63.8 | 7.8 | 4700 | 3500 |
计算过程
步骤1:数据标准化
对各指标计算均值和标准差,进行Z-score标准化。例如对 \(X_1\):
- 均值:\(\bar{x}_1 = \frac{12.5+10.8+15.2+8.6+11.3+14.1+9.5+13.6}{8} = 11.95\)
- 标准差:\(s_1 = 2.24\)
标准化值:\(z_{A1} = \frac{12.5 - 11.95}{2.24} = 0.245\)
对全部数据执行同样的操作。
步骤2:计算相关系数矩阵
计算标准化数据的相关系数矩阵 \(R\)。在本案例中,可以观察到 \(X_1, X_2, X_3, X_5, X_6\) 之间有较强的正相关(相关系数大于0.85),而 \(X_4\) 与其他指标呈负相关(经济发展水平高的城市,固定资产投资增速反而较低)。
步骤3:特征值分解
求解相关系数矩阵的特征值:
| 主成分 | 特征值 \(\lambda_i\) | 贡献率 \(\eta_i\) | 累积贡献率 |
|---|---|---|---|
| \(F_1\) | 4.82 | 80.33% | 80.33% |
| \(F_2\) | 0.89 | 14.83% | 95.17% |
| \(F_3\) | 0.15 | 2.50% | 97.67% |
| \(F_4\) | 0.08 | 1.33% | 99.00% |
| \(F_5\) | 0.04 | 0.67% | 99.67% |
| \(F_6\) | 0.02 | 0.33% | 100.00% |
步骤4:确定主成分个数
前2个主成分的累积贡献率为95.17% > 85%,因此选取 \(m = 2\) 个主成分。
步骤5:计算主成分得分与综合排名
以两个主成分的贡献率为权重计算综合得分:
\[ F = \frac{80.33}{95.17} F_1 + \frac{14.83}{95.17} F_2 = 0.8441 F_1 + 0.1559 F_2 \]
| 城市 | \(F_1\) | \(F_2\) | 综合得分 \(F\) | 排名 |
|---|---|---|---|---|
| C | 1.652 | -0.213 | 1.361 | 1 |
| F | 1.105 | -0.085 | 0.920 | 2 |
| H | 0.812 | 0.024 | 0.689 | 3 |
| A | 0.315 | 0.118 | 0.284 | 4 |
| E | -0.124 | 0.205 | -0.073 | 5 |
| B | -0.518 | 0.462 | -0.365 | 6 |
| G | -1.203 | 0.315 | -0.966 | 7 |
| D | -2.039 | -0.826 | -1.849 | 8 |
结果分析
- 城市C排名第一:人均GDP最高(15.2万元),第三产业占比最大(68.1%),进出口总额领先,综合经济实力最强
- 第一主成分的经济含义:载荷分析表明,\(F_1\) 主要反映了经济总量和发展质量(\(X_1, X_2, X_3, X_5, X_6\) 载荷较大),可命名为“经济实力因子“
- 第二主成分的经济含义:\(F_2\) 主要反映了投资增长潜力(\(X_4\) 载荷较大),可命名为“发展潜力因子“
- 城市D排名末位:各项经济指标均较低,虽然固定资产投资增速最高(12.3%),但整体经济基础薄弱
Python代码实现
import numpy as np
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
# ============================================================
# 主成分分析综合评价 - 城市经济发展水平案例
# ============================================================
# 原始数据:8个城市,6个指标
# X1: 人均GDP(万元), X2: 城镇居民人均可支配收入(万元),
# X3: 第三产业占比(%), X4: 固定资产投资增速(%),
# X5: 社会消费品零售总额(亿元), X6: 进出口总额(亿元)
cities = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H']
indicators = ['人均GDP', '人均收入', '三产占比', '投资增速', '消费总额', '进出口额']
data = np.array([
[12.5, 5.8, 62.3, 8.2, 4500, 3200],
[10.8, 5.2, 55.6, 10.5, 3800, 2500],
[15.2, 6.5, 68.1, 6.8, 5200, 4100],
[8.6, 4.5, 48.2, 12.3, 2900, 1800],
[11.3, 5.4, 58.9, 9.1, 4100, 2800],
[14.1, 6.2, 65.7, 7.5, 4900, 3800],
[9.5, 4.8, 51.4, 11.6, 3200, 2100],
[13.6, 6.0, 63.8, 7.8, 4700, 3500],
])
# ============================================================
# 第一步:数据标准化
# ============================================================
scaler = StandardScaler()
data_standardized = scaler.fit_transform(data)
print("=" * 60)
print("标准化后的数据(Z-score):")
print("=" * 60)
print(f"{'城市':<6}", end="")
for ind in indicators:
print(f"{ind:<10}", end="")
print()
for i, city in enumerate(cities):
print(f"{city:<6}", end="")
for j in range(len(indicators)):
print(f"{data_standardized[i, j]:<10.4f}", end="")
print()
# ============================================================
# 第二步:计算相关系数矩阵
# ============================================================
correlation_matrix = np.corrcoef(data_standardized, rowvar=False)
print("\n" + "=" * 60)
print("相关系数矩阵:")
print("=" * 60)
print(f"{'':8}", end="")
for ind in indicators:
print(f"{ind:<8}", end="")
print()
for i, ind in enumerate(indicators):
print(f"{ind:<8}", end="")
for j in range(len(indicators)):
print(f"{correlation_matrix[i, j]:<8.4f}", end="")
print()
# ============================================================
# 第三步:特征值分解(使用numpy实现)
# ============================================================
eigenvalues, eigenvectors = np.linalg.eigh(correlation_matrix)
# 按特征值从大到小排序
idx = np.argsort(eigenvalues)[::-1]
eigenvalues = eigenvalues[idx]
eigenvectors = eigenvectors[:, idx]
print("\n" + "=" * 60)
print("特征值分解结果:")
print("=" * 60)
total_var = np.sum(eigenvalues)
cumulative = 0
print(f"{'主成分':<10}{'特征值':<12}{'贡献率(%)':<14}{'累积贡献率(%)':<14}")
print("-" * 50)
for i in range(len(eigenvalues)):
contribution = eigenvalues[i] / total_var * 100
cumulative += contribution
print(f"F{i+1:<9}{eigenvalues[i]:<12.4f}{contribution:<14.2f}{cumulative:<14.2f}")
# ============================================================
# 第四步:确定主成分个数(累积贡献率 >= 85%)
# ============================================================
cumulative_ratio = np.cumsum(eigenvalues) / total_var
n_components = np.argmax(cumulative_ratio >= 0.85) + 1
print(f"\n选取主成分个数:m = {n_components}(累积贡献率 >= 85%)")
print(f"前 {n_components} 个主成分的累积贡献率:{cumulative_ratio[n_components-1]*100:.2f}%")
# ============================================================
# 第五步:使用sklearn的PCA进行验证
# ============================================================
pca = PCA(n_components=n_components)
scores = pca.fit_transform(data_standardized)
print("\n" + "=" * 60)
print("主成分载荷矩阵(各指标在主成分上的载荷):")
print("=" * 60)
loadings = pca.components_.T * np.sqrt(pca.explained_variance_)
print(f"{'指标':<10}", end="")
for i in range(n_components):
print(f"{'F' + str(i+1):<12}", end="")
print()
for i, ind in enumerate(indicators):
print(f"{ind:<10}", end="")
for j in range(n_components):
print(f"{loadings[i, j]:<12.4f}", end="")
print()
# ============================================================
# 第六步:计算综合评价得分
# ============================================================
# 以各主成分的方差贡献率(在所选主成分中的占比)为权重
weights = pca.explained_variance_ratio_ / pca.explained_variance_ratio_.sum()
print("\n" + "=" * 60)
print(f"综合评价权重:")
print("=" * 60)
for i in range(n_components):
print(f" F{i+1} 的权重:{weights[i]:.4f}")
# 计算综合得分
comprehensive_scores = scores @ weights
print("\n" + "=" * 60)
print("各城市主成分得分与综合评价结果:")
print("=" * 60)
print(f"{'城市':<6}", end="")
for i in range(n_components):
print(f"{'F' + str(i+1):<10}", end="")
print(f"{'综合得分':<12}{'排名':<6}")
print("-" * 50)
# 按综合得分排序
ranking = np.argsort(-comprehensive_scores)
for rank, idx_val in enumerate(ranking):
print(f"{cities[idx_val]:<6}", end="")
for j in range(n_components):
print(f"{scores[idx_val, j]:<10.4f}", end="")
print(f"{comprehensive_scores[idx_val]:<12.4f}{rank + 1:<6}")
# ============================================================
# 可视化:碎石图与主成分散点图
# ============================================================
fig, axes = plt.subplots(1, 2, figsize=(14, 5))
# 碎石图(Scree Plot)
pca_full = PCA()
pca_full.fit(data_standardized)
axes[0].plot(range(1, len(pca_full.explained_variance_ratio_) + 1),
pca_full.explained_variance_ratio_ * 100,
'bo-', linewidth=2, markersize=8)
axes[0].axhline(y=100/len(indicators), color='r', linestyle='--',
label=f'平均贡献率 ({100/len(indicators):.1f}%)')
axes[0].set_xlabel('主成分序号', fontsize=12)
axes[0].set_ylabel('方差贡献率 (%)', fontsize=12)
axes[0].set_title('碎石图(Scree Plot)', fontsize=14)
axes[0].legend(fontsize=10)
axes[0].grid(True, alpha=0.3)
axes[0].set_xticks(range(1, len(indicators) + 1))
# 主成分散点图(前两个主成分)
if n_components >= 2:
axes[1].scatter(scores[:, 0], scores[:, 1], c='steelblue', s=100, zorder=5)
for i, city in enumerate(cities):
axes[1].annotate(city, (scores[i, 0], scores[i, 1]),
textcoords="offset points", xytext=(5, 5),
fontsize=11, fontweight='bold')
axes[1].axhline(y=0, color='gray', linestyle='-', linewidth=0.5)
axes[1].axvline(x=0, color='gray', linestyle='-', linewidth=0.5)
axes[1].set_xlabel(f'第一主成分 F1 ({pca.explained_variance_ratio_[0]*100:.1f}%)',
fontsize=12)
axes[1].set_ylabel(f'第二主成分 F2 ({pca.explained_variance_ratio_[1]*100:.1f}%)',
fontsize=12)
axes[1].set_title('主成分得分散点图', fontsize=14)
axes[1].grid(True, alpha=0.3)
plt.tight_layout()
plt.savefig('pca_evaluation_result.png', dpi=150, bbox_inches='tight')
plt.show()
print("\n" + "=" * 60)
print("分析完成!图表已保存为 pca_evaluation_result.png")
print("=" * 60)
代码输出解读
运行上述代码后,可以获得以下关键结果:
- 相关系数矩阵:直观反映各指标间的相关程度,相关性强的指标适合做PCA
- 碎石图:帮助确定保留的主成分个数,选取“陡坡“变为“平坦“的转折点
- 载荷矩阵:揭示各主成分的实际经济含义
- 综合排名:给出最终的城市经济发展水平排序
应用注意事项与局限性
适用条件
-
指标间应存在较强相关性:若各指标相互独立,PCA降维效果有限。可通过Bartlett球形检验判断:
- \(H_0\):相关系数矩阵为单位阵(指标间无相关)
- 若拒绝 \(H_0\)(\(p < 0.05\)),则适合进行PCA
-
KMO检验:KMO值越接近1,表明变量间的偏相关性越强,越适合做PCA:
- KMO > 0.9:非常适合
- 0.8 < KMO < 0.9:适合
- 0.7 < KMO < 0.8:一般
- KMO < 0.6:不适合
-
样本量要求:一般要求样本量 \(n\) 至少为变量数 \(p\) 的5倍以上
注意事项
-
数据标准化:由于PCA对量纲敏感,在计算前必须进行标准化处理。若指标量纲差异悬殊,未标准化的结果将被方差大的变量主导
-
主成分个数选择:
- 累积贡献率准则(85%)是经验阈值,可根据实际问题适当调整
- 碎石图法更为直观,但有时“肘部“不明显
- Kaiser准则(特征值 > 1)也可参考,但并非总是可靠
-
主成分命名与解释:
- 主成分是原始变量的线性组合,其含义需要结合载荷矩阵分析
- 若载荷结构不清晰,可考虑对载荷矩阵进行旋转(如Varimax旋转),但旋转后方差最大化性质不再成立
-
正负向指标处理:
- 若存在逆向指标(如污染排放量),需要在标准化前进行正向化处理
- 常用方法:取倒数、取负数、或用最大值减去该值
-
综合得分可能为负值:PCA综合得分是标准化后数据的线性组合,其均值为0,因此部分对象得分为负属于正常现象,不代表绝对意义上的“差“
局限性
-
线性假设:PCA基于线性变换,对非线性结构的数据降维效果不佳。若数据呈非线性分布,可考虑核主成分分析(Kernel PCA)
-
方差不等于重要性:PCA以方差大小衡量信息量,但方差最大的方向并不一定是最有评价意义的方向。某些方差小但对区分评价对象至关重要的信息可能被忽略
-
可解释性较弱:主成分是所有原始变量的线性组合,每个主成分往往包含所有变量的信息,导致经济含义模糊,不如原始指标直观
-
对异常值敏感:PCA基于协方差/相关系数矩阵,异常值会显著影响协方差结构,从而影响主成分方向。建议先进行异常值检测与处理
-
无法处理定性指标:PCA要求数据为连续型变量,对于分类变量(如等级评价),需要先进行数量化处理或使用多重对应分析(MCA)
与其他评价方法的比较
| 方法 | 赋权方式 | 优势 | 劣势 |
|---|---|---|---|
| PCA | 客观(方差驱动) | 客观性强,消除共线性 | 可解释性弱 |
| 层次分析法 | 主观(专家判断) | 逻辑清晰,可解释性强 | 主观性强 |
| TOPSIS | 需外部权重 | 充分利用数据信息 | 依赖权重确定方法 |
| 熵权法 | 客观(信息熵) | 完全客观 | 忽略指标实际意义 |
实践建议
- 组合使用:可将PCA确定的权重与AHP的主观权重进行组合,实现主客观统一
- 稳健性检验:改变主成分个数或使用不同的标准化方法,检验排名结果的稳定性
- 结合领域知识:PCA结果应结合专业知识进行解读,避免纯数学化的机械分析
- 数据预处理:重视异常值检测、缺失值处理和正向化等预处理步骤