Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

主成分分析评价法(PCA)

“主成分分析的核心思想是降维——用少数几个综合指标代替原来众多的相关指标,同时尽可能多地保留原始数据的信息。” —— Karl Pearson, 1901

基本原理

什么是主成分分析

主成分分析(Principal Component Analysis, PCA)是一种经典的多元统计分析方法,其核心目标是降维。在综合评价问题中,我们常常面对大量相关性较强的评价指标。这些指标之间的重叠信息不仅增加了计算复杂度,还可能导致评价结果失真。PCA通过线性变换,将原始的多个相关指标转化为少数几个互不相关的综合指标(即主成分),从而实现降维与信息浓缩。

方差最大化原则

PCA的数学本质是寻找一组新的正交坐标系,使得数据在新坐标轴上的投影方差最大。具体而言:

  • 第一主成分:在所有线性组合中,选取使方差最大的方向,即数据信息量最大的方向
  • 第二主成分:在与第一主成分正交(不相关)的约束下,选取方差次大的方向
  • 第 \(k\) 主成分:在与前 \(k-1\) 个主成分都正交的约束下,选取方差最大的方向

通过这种方式,前几个主成分通常能够解释原始数据总方差的绑大部分(如85%以上),从而实现“用少量变量概括大部分信息“的目标。

与评价问题的结合

在综合评价中,PCA的优势在于:

  1. 客观赋权:主成分的权重由数据本身的方差结构决定,无需人为设定
  2. 消除多重共线性:主成分之间互不相关,避免了指标间信息重叠的干扰
  3. 降维简化:将高维评价问题转化为低维问题,便于排序与可视化
  4. 信息量可度量:通过累积贡献率可以量化保留了多少原始信息

数学基础

协方差矩阵

设有 \(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\)
A12.55.862.38.245003200
B10.85.255.610.538002500
C15.26.568.16.852004100
D8.64.548.212.329001800
E11.35.458.99.141002800
F14.16.265.77.549003800
G9.54.851.411.632002100
H13.66.063.87.847003500

计算过程

步骤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.8280.33%80.33%
\(F_2\)0.8914.83%95.17%
\(F_3\)0.152.50%97.67%
\(F_4\)0.081.33%99.00%
\(F_5\)0.040.67%99.67%
\(F_6\)0.020.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\)排名
C1.652-0.2131.3611
F1.105-0.0850.9202
H0.8120.0240.6893
A0.3150.1180.2844
E-0.1240.205-0.0735
B-0.5180.462-0.3656
G-1.2030.315-0.9667
D-2.039-0.826-1.8498

结果分析

  1. 城市C排名第一:人均GDP最高(15.2万元),第三产业占比最大(68.1%),进出口总额领先,综合经济实力最强
  2. 第一主成分的经济含义:载荷分析表明,\(F_1\) 主要反映了经济总量和发展质量(\(X_1, X_2, X_3, X_5, X_6\) 载荷较大),可命名为“经济实力因子“
  3. 第二主成分的经济含义:\(F_2\) 主要反映了投资增长潜力(\(X_4\) 载荷较大),可命名为“发展潜力因子“
  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)

代码输出解读

运行上述代码后,可以获得以下关键结果:

  1. 相关系数矩阵:直观反映各指标间的相关程度,相关性强的指标适合做PCA
  2. 碎石图:帮助确定保留的主成分个数,选取“陡坡“变为“平坦“的转折点
  3. 载荷矩阵:揭示各主成分的实际经济含义
  4. 综合排名:给出最终的城市经济发展水平排序

应用注意事项与局限性

适用条件

  1. 指标间应存在较强相关性:若各指标相互独立,PCA降维效果有限。可通过Bartlett球形检验判断:

    • \(H_0\):相关系数矩阵为单位阵(指标间无相关)
    • 若拒绝 \(H_0\)(\(p < 0.05\)),则适合进行PCA
  2. KMO检验:KMO值越接近1,表明变量间的偏相关性越强,越适合做PCA:

    • KMO > 0.9:非常适合
    • 0.8 < KMO < 0.9:适合
    • 0.7 < KMO < 0.8:一般
    • KMO < 0.6:不适合
  3. 样本量要求:一般要求样本量 \(n\) 至少为变量数 \(p\) 的5倍以上

注意事项

  1. 数据标准化:由于PCA对量纲敏感,在计算前必须进行标准化处理。若指标量纲差异悬殊,未标准化的结果将被方差大的变量主导

  2. 主成分个数选择

    • 累积贡献率准则(85%)是经验阈值,可根据实际问题适当调整
    • 碎石图法更为直观,但有时“肘部“不明显
    • Kaiser准则(特征值 > 1)也可参考,但并非总是可靠
  3. 主成分命名与解释

    • 主成分是原始变量的线性组合,其含义需要结合载荷矩阵分析
    • 若载荷结构不清晰,可考虑对载荷矩阵进行旋转(如Varimax旋转),但旋转后方差最大化性质不再成立
  4. 正负向指标处理

    • 若存在逆向指标(如污染排放量),需要在标准化前进行正向化处理
    • 常用方法:取倒数、取负数、或用最大值减去该值
  5. 综合得分可能为负值:PCA综合得分是标准化后数据的线性组合,其均值为0,因此部分对象得分为负属于正常现象,不代表绝对意义上的“差“

局限性

  1. 线性假设:PCA基于线性变换,对非线性结构的数据降维效果不佳。若数据呈非线性分布,可考虑核主成分分析(Kernel PCA)

  2. 方差不等于重要性:PCA以方差大小衡量信息量,但方差最大的方向并不一定是最有评价意义的方向。某些方差小但对区分评价对象至关重要的信息可能被忽略

  3. 可解释性较弱:主成分是所有原始变量的线性组合,每个主成分往往包含所有变量的信息,导致经济含义模糊,不如原始指标直观

  4. 对异常值敏感:PCA基于协方差/相关系数矩阵,异常值会显著影响协方差结构,从而影响主成分方向。建议先进行异常值检测与处理

  5. 无法处理定性指标:PCA要求数据为连续型变量,对于分类变量(如等级评价),需要先进行数量化处理或使用多重对应分析(MCA)

与其他评价方法的比较

方法赋权方式优势劣势
PCA客观(方差驱动)客观性强,消除共线性可解释性弱
层次分析法主观(专家判断)逻辑清晰,可解释性强主观性强
TOPSIS需外部权重充分利用数据信息依赖权重确定方法
熵权法客观(信息熵)完全客观忽略指标实际意义

实践建议

  1. 组合使用:可将PCA确定的权重与AHP的主观权重进行组合,实现主客观统一
  2. 稳健性检验:改变主成分个数或使用不同的标准化方法,检验排名结果的稳定性
  3. 结合领域知识:PCA结果应结合专业知识进行解读,避免纯数学化的机械分析
  4. 数据预处理:重视异常值检测、缺失值处理和正向化等预处理步骤