层次分析法(AHP)在多准则决策中的应用

摘要

本文针对两类多准则决策问题建立层次分析(AHP)模型。问题一为三款手机在四个指标上的综合评价,问题二为四个旅游目的地的选择。建模过程包括:构建目标层—准则层—方案层的层次结构;采用 1–9 标度法构造判断矩阵;通过最大特征值计算一致性指标 CI 与一致性比例 CR 并做检验;分别用算术平均法、几何平均法与特征值法计算权重并取均值。结果表明:手机案例中小米(0.359)> 华为(0.353)> 苹果(0.288);旅游案例中张家界(0.381)> 青岛(0.238)> 丽江(0.222)> 厦门(0.159)。一致性检验能够有效识别判断矩阵中的逻辑矛盾——问题一中首个判断矩阵 CR = 0.225 未通过,修正后降至 0.0054,说明该步骤是保证权重合理性的关键环节。

关键词:层次分析法;判断矩阵;一致性检验;特征值;权重


一、问题描述

问题一 对三款手机(小米、华为、苹果)进行综合评价。原始数据为三款手机在四个指标上的打分矩阵,原数据未标注各指标的具体含义,本文按位置记为指标①②③④。

问题二 暑假出游目的地在丽江、厦门、青岛、张家界四地中选择。需综合考虑四个准则:交通便利性、旅游资源丰富程度、旅途开销、安全和卫生情况。要求自行构造准则层判断矩阵与方案层得分,建立综合评价模型。

二、模型假设

  1. 各评价指标之间相互独立,不存在显著的交互作用;
  2. 决策者给出的两两比较判断具有内在一致性倾向,即不存在根本性的逻辑矛盾;
  3. 判断矩阵中的标度值能真实反映决策者的偏好强度;
  4. 方案层各指标得分均已统一方向,即均为"数值越大越优";
  5. 不考虑指标数据本身的测量误差。

三、符号说明

符号含义
$A$判断矩阵,$n \times n$ 正互反矩阵
$a_{ij}$第 $i$ 个元素相对第 $j$ 个元素的重要程度
$n$判断矩阵阶数
$\lambda_{max}$判断矩阵的最大特征值
$CI$一致性指标
$RI$平均随机一致性指标
$CR$一致性比例
$\mathbf{w}$权重向量
$m$方案(备选)个数
$res1$方案层归一化得分矩阵

四、模型建立与求解

4.1 层次结构构建

将问题分解为三个层次:

层级问题一问题二
目标层选择最优手机选择最优旅游地
准则层指标①②③④交通便利性、旅游资源、旅途开销、安全卫生
方案层小米、华为、苹果丽江、厦门、青岛、张家界

4.2 判断矩阵构造

对同一层元素两两比较,按 1–9 标度法赋值,构造正互反矩阵 $A = (a_{ij})_{n \times n}$,满足 $a_{ij} = 1/a_{ji}$,$a_{ii} = 1$。

问题二的准则层判断矩阵为:

交通资源开销安全
交通121/23
资源1/211/22
开销2213
安全1/31/21/31

4.3 一致性检验

判断矩阵由主观赋值产生,可能出现"甲优于乙、乙优于丙、而丙又优于甲"的逻辑矛盾,因此必须检验一致性。

由最大特征值计算一致性指标:

$$ CI = \frac{\lambda_{max} - n}{n - 1} $$

查表得平均随机一致性指标 $RI$(本文取 $n=4$ 时 $RI = 0.90$),计算一致性比例:

$$ CR = \frac{CI}{RI} $$

当 $CR < 0.1$ 时认为一致性可以接受。

问题一的一致性检验(含失败案例)

首个判断矩阵经计算得 $\lambda_{max} = 4.6075$,$CI = 0.2025$,$CR = 0.225 > 0.1$,未通过检验。分析其矛盾来源后调整指标②与指标③的相对重要性,得到修正矩阵,重算得 $\lambda_{max} = 4.0145$,$CI = 0.0048$,$CR = 0.0054 < 0.1$,通过检验。

$CR$ 由 0.225 降至 0.0054,说明修正后判断矩阵的内部矛盾基本消除。

问题二的一致性检验

$\lambda_{max} = 4.0710$,$CI = 0.0237$,$CR = 0.0263 < 0.1$,通过检验。

4.4 权重计算

采用三种方法分别计算权重,以便相互验证。

(1)算术平均法:判断矩阵按列归一化后,对每行求平均。

$$ w_i = \frac{1}{n}\sum_{j=1}^{n}\frac{a_{ij}}{\sum_{k=1}^{n}a_{kj}} $$

(2)几何平均法:每行元素连乘后开 $n$ 次方,再归一化。

$$ w_i = \frac{\left(\prod_{j=1}^{n}a_{ij}\right)^{1/n}}{\sum_{k=1}^{n}\left(\prod_{j=1}^{n}a_{kj}\right)^{1/n}} $$

(3)特征值法:取最大特征值对应的特征向量,归一化后作为权重。

$$ A\mathbf{w} = \lambda_{max}\mathbf{w} $$

三种方法计算结果如下。

问题一(修正后的判断矩阵)

指标算术平均法几何平均法特征值法
①0.4824070.4831890.482886
②0.0882870.0882180.088150
③0.1575080.1568760.156990
④0.2717980.2717170.271974

问题二

准则算术平均法几何平均法特征值法
交通便利性0.2930310.2922220.292590
旅游资源0.1871900.1867140.184948
旅途开销0.4118200.4132650.415493
安全卫生0.1079580.1077990.106969

三种方法结果高度一致(差异在小数点后第三位),说明判断矩阵较为规整。取三者均值作为最终权重:

问题一:$\mathbf{w} = [0.482827,\ 0.088218,\ 0.157125,\ 0.271830]^\top$

问题二:$\mathbf{w} = [0.292615,\ 0.186284,\ 0.413526,\ 0.107575]^\top$

4.5 综合得分计算

方案层得分矩阵按列归一化,消除各指标的量纲差异:

$$ b_{ij} = \frac{x_{ij}}{\sum_{i=1}^{m} x_{ij}} $$

再与权重向量加权求和得到各方案综合得分:

$$ S_i = \sum_{j=1}^{n} b_{ij} \cdot w_j $$

问题一方案层原始数据与归一化结果

手机指标①指标②指标③指标④
小米0.3227090.4363640.2903230.437908
华为0.2788840.4545450.3870970.431373
苹果0.3984060.1090910.3225810.130719

问题二方案层得分

城市交通资源开销安全
丽江7917
厦门9809
青岛9818
张家界6938

五、结果分析

问题一结果

手机综合得分排名
小米0.3591
华为0.3532
苹果0.2883

小米与华为得分接近(0.359 与 0.353),苹果明显落后。指标①权重最高(48.3%),苹果虽在指标①上取得最高分,但在权重第二高的指标④上仅为 0.131,被显著拉低。

问题二结果

城市综合得分排名
张家界0.38101
青岛0.23842
丽江0.22163
厦门0.15904

「旅途开销」权重最高(41.4%),张家界在该准则上得分为 3(其余三地分别为 1、0、1),因此在加权求和后明显领先。厦门在交通与安全两项均取得最高分,但开销得分为 0,被权重最高的准则直接拉至末位。

这一结果揭示 AHP 的一个显著特征:最终排序往往由权重最高的准则主导,因此判断矩阵的合理性比计算方法的选择更为重要——这正是必须进行一致性检验的原因。

六、模型评价

优点

  1. 将定性判断定量化,能够处理难以直接量化的评价准则;
  2. 一致性检验提供了判断矩阵自洽性的量化判据,避免主观赋值中的逻辑矛盾;
  3. 三种权重计算方法结果接近,可相互验证,提高结果可信度;
  4. 模型结构清晰,计算量小,易于实现与推广。

局限

  1. 权重仍来源于决策者的主观赋值,不同决策者可能给出不同结果;
  2. 当准则或方案数量较多时,判断矩阵的数量与规模迅速增大;
  3. 当 $n > 9$ 时一致性难以保证;
  4. 增加或删除备选方案可能引起排序逆转现象;
  5. 问题一中四个指标未明确命名,方案层得分是否已统一方向无法核验,若其中存在成本型指标则需先做正向化处理。

附录:Python 代码

附录 A 问题一(三款手机评价)

"""
对手机的结果进行评分
"""

# 注意前面的代码没有使用numpy

# 对数据进行归一化
a = [
    [81, 48, 9, 67],
    [70, 50, 12, 66],
    [100, 12, 10, 20]
]

# 对每一列进行求和
a_sum = []
# 控制列
for j in range(len(a[0])):
    temp = 0
    # 控制行
    for i in range(len(a)):
        temp += a[i][j]
    a_sum.append(temp)
#print(a_sum)

# 数据归一化结果
res1 = []

for x in a:
    temp = []
    i = 0
    for y in x:
        # 每一个数据
        temp.append(y / a_sum[i])
        i += 1
    res1.append(temp)

print('数据归一化结果:')
for x in res1:
    print(x)
    print()


#############################################
print('-----------------------特征值---------------------')

# 求特征值

import numpy as np

# AHP 只能是方阵
A = np.array(
    [
        [1, 5, 3, 2],
        [1/5, 1, 2, 1/3],
        [1/3, 1/2, 1, 2],
        [1/2, 3, 1/2, 1]
    ]
)

# 特征值(包含虚部)
eigenvalues = np.linalg.eigvals(A)

# 只取实部
eigenvalues_real = np.real(eigenvalues)

print(eigenvalues_real)

# 最大特征值
print("最大特征值:" + str(np.max(eigenvalues_real)))

eigenvalues_real_max = np.max(eigenvalues_real)

"""
注意,我们有了最大特征值就可以去求 CI 了
"""

def fun(ci, ri):
    # 一致性检验

    print('-------------------一致性检验---------------------')

    print(f'CI = {ci}')

    print(f'CR = CI/RI = {ci / ri}')

    if ci / ri > 0.1:
        print("一致性检验不通过!!!")
        print("-->需要重新调整")
    else:
        print("一致性检验通过")

n = 4
# 警告⚠️:这个4是阶数,需要根据实际调整
CI = (eigenvalues_real_max - n) / (n - 1)
RI = 0.9 # 特征值:不用计算,根据RI特征值表来取值
fun(CI, RI)

# 重新计算合乎逻辑的矩阵
A1 = np.array(
    [
        [1, 5, 3, 2],
        [1/5, 1, 1/2, 1/3],
        [1/3, 2, 1, 1/2],
        [1/2, 3, 2, 1]
    ]
)

# 正确的最大特征值
x = np.max(np.real(np.linalg.eigvals(A1)))

CI = (x - n) / (n - 1)
RI = 0.9
fun(CI, RI)

"""
求权重
"""

print('--------------------算数平均法--------------------')

A1_norm = A1 / A1.sum(axis=0) # 这样子可以快速进行归一化计算

print('归一化(按列):')
print(A1_norm)


print('权重(求平均值):')
w1 = A1_norm.mean(axis=1)
print(w1) # mean是求均值(axis=1是按行)


print('--------------------几何平均法--------------------')

w2 = np.prod(A1, axis=1) ** (1 / n) # np的连乘函数 并且 开n次根

w2 = w2 / w2.sum(axis=0)

print('权重:')
print(w2)


print('--------------------特征值法--------------------')

# 特征值、特征向量
eigenvalues, eigenvectors = np.linalg.eig(A1)

# 最大特征值的下标
k = np.argmax(np.real(eigenvalues))

# 对应特征向量(单位长度)
w3 = np.real(eigenvectors[:, k])

w3 = w3 / w3[-1] # (可去除的操作)除以最后一个分量,使得最后一个分量为1,复刻b站的数据

print('特征向量')
print(w3)


print('权重:')
w3 = w3 / w3.sum(axis=0)

print(w3)

print('############### 三个方案的结果对比 ###############')

print(w1)
print(w2)
print(w3)

print('############### 计算最终的权重 ###############')

A2 = np.array(
    [w1, w2, w3]
)

A3 = np.array(
    A2.sum(axis=0) / 3
)

print(A3)


print('############### 最终结果 ###############')
# 归一化结果:res1

result = np.array(res1) @ A3 # 归一化矩阵 × 权重向量

for name, score in zip(['小米', '华为', '苹果'], result):
    print(f'{name}: {score:.3f}')

附录 B 问题二(旅游地评价)

import numpy as np

"""
暑假想和朋友一起出去旅游,
暂定计划有
    丽江、厦门、青岛、张家界,
    需要考虑
        交通便利性、
        旅游资源丰富程度、
        旅途开销、
        安全和卫生情况,
请自行构建方案层、准则层判断矩阵,建立综合评价模型进行评价
"""

# 构建目标层、准则层、方案层
"""
目标层:旅游
准则层:交通便利性、旅游资源丰富程度、旅途开销、安全和卫生情况
方案层:丽江、厦门、青岛、张家界
"""

# 先主观(或者客观)构建权重的矩阵

"""
                交通便利性   旅游资源丰富程度    旅途开销    安全和卫生情况

交通便利性           1             2             1/2           3

旅游资源丰富程度     1/2            1             1/2           2

旅途开销             2             2              1            3

安全和卫生情况       1/3           1/2            1/3           1
"""

# 构建这个判断矩阵
# 这个是判断矩阵
A = np.array([
    [1, 2, 1/2, 3],
    [1/2, 1, 1/2, 2],
    [2, 2, 1, 3],
    [1/3, 1/2, 1/3, 1]
])

n = len(A)

# 对数据进行归一化处理
# 这个是判断矩阵的归一化
A_norm = A / A.sum(axis=0)

print(f'归一化处理后的矩阵为:\n{A_norm}')
"""
[[0.26086957 0.36363636 0.21428571 0.33333333]
 [0.13043478 0.18181818 0.21428571 0.22222222]
 [0.52173913 0.36363636 0.42857143 0.33333333]
 [0.08695652 0.09090909 0.14285714 0.11111111]]
"""

# 判断是否通过一致性检验

# -求特征向量
# 特征值、特征向量
eigenvalues, eigenvectors = np.linalg.eig(A)

eigenvalues_max = np.max(np.real(eigenvalues))

print(f'最大特征值为:\n{eigenvalues_max}')

# 现在开始求CI

CI = (eigenvalues_max - n) / (n - 1)

print(f'一致性指标CI为:\n{CI}')

# 我们是 n = 4,所以我们使用RI = 0.90
RI = 0.90

CR = CI / RI 

print(f'一致性指标CR为:\n{CR}')

if CR < 0.1:
    print("--> 通过一致性检验")
else:
    print("--> 不通过一致性检验")

print('--------------------------------------------------------')
print('开始求权重')
print('--------------------------------------------------------')
print('--> 算数平均法:')

# 1.判断矩阵按列归一化(已算)
w1 = A_norm

# 2.将归一化的各列相加(=一行求和)后除以n得到权重 --> 求每行的平均数
# w1 = w1.sum(axis=1) / n
w1 = w1.mean(axis=1)

print(f'权重:{w1}')

print('--> 几何平均法:')

# 1.判断矩阵的元素按行相乘得到一个新的列向量
w2 = np.prod(A, axis=1)

# 2.将列向量的每个元素开n次方
w2 = w2  ** (1/n)

# 3.对该列向量进行归一化即可得到权重向量
w2 = w2 / w2.sum(axis=0)

print(f'权重:{w2}')

print('--> 特征值法:')
# 1.求特征值、特征向量(已经求过了)
# eigenvalues, eigenvectors = np.linalg.eig(A)

# 2.计算出矩阵的最大特征值以及特征向量
k = np.argmax(np.real(eigenvalues)) # 最大特征值的下标
w3 = np.real(eigenvectors[:, k]) # 取最大特征值对应的特征向量(去掉虚部)

# 3.进行归一化
w3 = w3 / w3.sum(axis=0)
print(f'权重:{w3}')

print('--------------------------------------------------------')
print('三个方法计算的结果为')
print('--------------------------------------------------------')

W = np.array([w1, w2, w3])
print(W)

print('--------------------------------------------------------')
print('求最终的权重')
print('--------------------------------------------------------')

w = W.mean(axis=0)
print(f'最终的权重为:\n={w}\n')
print(f'交通便利性:\t{w[0]}')
print(f'旅游资源丰富程度:\t{w[1]}')
print(f'旅途开销:\t{w[2]}')
print(f'安全和卫生情况:\t{w[3]}')

print('--------------------------------------------------------')
print('计算得分')
print('--------------------------------------------------------')

# 这个是叫AI生成的(一般好像是自己填的)。
"""
        交通  资源  开销  安全
丽江    [  7,   9,   1,   7  ]
厦门    [  9,   8,   0,   9  ]
青岛    [  9,   8,   1,   8  ]
张家界  [  6,   9,   3,   8  ]
"""

data = np.array(
    [
        [7, 9, 1, 7],
        [9, 8, 0, 9],
        [9, 8, 1, 8],
        [6, 9, 3, 8]
    ]
)

data = data / data.sum(axis=0)

# 矩阵乘法
result = data @ w

print(result)

附录 C 运行结果

附录 A(问题一)关键输出

最大特征值:4.6075371100223474
CI = 0.20251237000744915
CR = CI/RI = 0.22501374445272126
一致性检验不通过!!!
-->需要重新调整
CI = 0.004840319544088996
CR = CI/RI = 0.005378132826765551
一致性检验通过
############### 计算最终的权重 ###############
[0.48282707 0.08821841 0.15712474 0.27182977]
############### 最终结果 ###############
小米: 0.359
华为: 0.353
苹果: 0.288

附录 B(问题二)关键输出

最大特征值为:
4.071012577499603
一致性指标CI为:
0.02367085916653444
一致性指标CR为:
0.02630095462948271
--> 通过一致性检验
最终的权重为:
=[0.29261469 0.18628403 0.41352589 0.10757538]

交通便利性:    0.2926146940122872
旅游资源丰富程度:    0.18628402925285126
旅途开销:    0.41352589411478413
安全和卫生情况:    0.10757538262007749
计算得分
[0.22162206 0.15903977 0.23838321 0.38095496]

注:本文 $RI$ 取 Saaty 原始表与司守奎《数学建模算法与应用》中的 $RI(4) = 0.90$。部分文献(如 Salomon 与 Gomes 2024)给出 $0.89$,两者差异不影响一致性检验结论。