🌈🌈🌈往期精选内容:
💖【数学建模】图论模型:从Dijkstra算法到最小费用最大流实战-CSDN博客
💖【数学建模】主成分分析(PCA)详解:从理论到实践的全面指南-CSDN博客
💖【数学建模】数据拟合与插值技术全解析:从线性插值到Logistic模型实战CSDN博客
💖【数学建模】熵权法——基于2021全国大学生数学建模C题供应商评价数学建模实战-CSDN博客
💖MNIST手写数字识别——基于PyTorch的MLP模型的Python代码-CSDN博客
层次分析法(AHP):从理论到实战的全面解析
💖引言
在现实生活中,我们常常面临各种复杂的决策问题,例如选择旅行目的地、投资项目评估、供应商选择等。这些决策往往涉及多个准则和备选方案,如何综合考虑各个因素的重要性并做出科学合理的决策是一个关键问题。层次分析法(Analytic Hierarchy Process,AHP
)作为一种结构化的决策方法,为我们提供了一种有效的解决方案。它通过将复杂问题分解为多个层次,并通过两两比较的方式确定各因素的相对重要性,从而帮助我们做出更加理性和客观的决策。
📚一、层次分析法(AHP)
🚀1.1、概念
层次分析法(AHP)
是一种系统化、层次化的多目标综合评价方法,由美国运 筹学家托马斯·L·萨蒂(Thomas L. Saaty)在20世纪70年代提出。该方法适用于处 理难以量化且结构复杂的决策问题。AHP
通过将决策问题分解为多个组成要素, 并根据各要素之间的关系进行分组,从而构建递阶层次结构。通过对各要素的相互 比较,确定其相对重要性,并依据这些相对重要性计算得分,对待评价的目标进行排序,从而得出最终的评价结果。
🚀1.2、AHP的优缺点
优点:
- 系统性:将复杂问题分解为多个层次和要素,使问题更加系统、清晰,有助于全面考虑问题。例如,在企业战略规划中,
AHP
可以将战略目标分解为多个准则和方案,使决策过程更加条理化。 - 实用性:结合定性和定量分析,能处理许多传统最优化技术无法着手的实际问题,应用范围广泛。例如,在项目管理中,
AHP
可以结合项目成员的经验判断和实际数据,对项目风险进行评估。 - 简洁性:计算简便,结果明确,易于理解和掌握。例如,
AHP
的判断矩阵构造和权重计算过程相对简单,即使是没有深厚数学背景的人也能较快掌握。 - 灵活性强:适用于多目标、多准则的复杂决策问题。例如,在多指标综合评估中,
AHP
可以灵活地处理多个目标和准则之间的关系。 - 客观性:通过两两比较的方式,确定各要素对整个问题的相对重要性,避免了主观臆断的误差,使得分析结果更加客观。例如,在供应商选择中,
AHP
可以通过对供应商的各项指标进行两两比较,得出相对客观的评估结果。
缺点:
- 主观性强:判断矩阵的构造依赖于专家经验和主观判断,可能导致结果的偏差。例如,在不同专家对同一问题的看法存在差异时,
AHP
的结果可能会受到较大影响。 - 计算繁琐:当问题规模较大时,计算过程可能较为复杂和耗时。例如,在涉及多个准则和方案的大型决策问题中,
AHP
的计算量会显著增加。 - 过于依赖专家意见:需要专家对各要素进行两两比较和打分,如果专家意见存在偏差或不够权威,将直接影响分析结果的准确性。例如,在某些领域缺乏权威专家时,
AHP
的可靠性可能会受到质疑。 - 无法处理不确定性问题:对于未来的变化和意外情况难以做出准确的预测。例如,在市场环境快速变化的情况下,
AHP
可能无法有效应对新的市场趋势。 - 比较、判断及结果计算过程粗糙:不适用于精度较高的问题。例如,在需要高精度计算的工程设计中,
AHP
的结果可能无法满足要求。
📚二、计算步骤
🚀2.1 、构建判断矩阵
在专家打分过程中对数据进行的正向化处理。同时根据原始数据矩阵,构建判断矩阵 A = a i j A = a_{ij} A=aij,其中 ( a i j ) (a_{ij}) (aij) 表示因素 i i i 相对于 j j j 的相对重要性。判断矩阵为 ( n × n ) (n \times n) (n×n)的正互反矩阵。
Saaty
9 级分制
标度 | 含义 |
---|---|
1 | 两因素相比,同等重要 |
3 | 两因素相比,前者比后者稍重要 |
5 | 两因素相比,前者比后者明显重要 |
7 | 两因素相比,前者比后者强烈重要 |
9 | 两因素相比,前者比后者极端重要 |
2、4、6、8 | 表示上述判断的中间值 |
倒数 | 相应两因素交换次序比较的重要性 |
参照表 的 Saaty
9 级分制两两比较相对重要性,得出相对权重的比值
w
i
w
j
\frac{w_i}{w_j}
wjwi ,以此建立一个判断矩阵。
🚀2.2、计算每个因素的权重向量
👉2.2.1、几何平均法
- 对于判断矩阵的第 (i) 行,计算该行的所有元素的几何平均值。几何平均法的计算公式如下:
w i = ( ∏ j = 1 n a i j ) 1 n , ( i = 0 , 1 , … , n ) w_i = \left( \prod_{j=1}^n a_{ij} \right)^{\frac{1}{n}}, \quad (i = 0, 1, \ldots, n) wi=(j=1∏naij)n1,(i=0,1,…,n) - 将步骤 1 中计算得到的几何平均数向量进行归一化处理,以得到每个因素的相对权重:
w i ′ = w i ∑ i = 1 n w i , ( i = 0 , 1 , … , n ) w_i' = \frac{w_i}{\sum_{i=1}^n w_i}, \quad (i = 0, 1, \ldots, n) wi′=∑i=1nwiwi,(i=0,1,…,n)
其中, ( w i ) (w_i) (wi)、 ( w i ′ ) (w_i') (wi′) 分别代表第 ( i ) (i) (i) 个特征权重的值,以及归一化后的值。
👉 2.2.2、算术平均法
- 对于判断矩阵 A = [ a 11 a 12 ⋯ a 1 n a 21 a 22 ⋯ a 2 n ⋮ ⋮ ⋱ ⋮ a n 1 a n 2 ⋯ a n n ] A = \begin{bmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{n1} & a_{n2} & \cdots & a_{nn} \end{bmatrix} A= a11a21⋮an1a12a22⋮an2⋯⋯⋱⋯a1na2n⋮ann ,先将其归一化,再将归一化的矩阵按列相加,并将每个元素除以 n n n 得到权重向量,即
- 归一化
S j = ∑ i = 1 n a i j S_j = \sum_{i=1}^{n}a_{ij} Sj=i=1∑naij - 权重向量:
w i ′ = S i ∑ i = 1 n S i w_i' = \frac{S_i}{\sum_{i=1}^n S_i} wi′=∑i=1nSiSi
👉2.2.3、 特征值法
在实际比赛和科研中,用特征值法求权重更常用也更方便,二者算出的权重相差也并不大,可实际生活中的数据一致性并非那么强,因此建议用特征值法。
- 特征值法:
A
w
=
λ
m
a
x
w
Aw=λ_ {max}w
Aw=λmaxw
最大特征值
λ
m
a
x
λ_ {max}
λmax对应的特征向量归一化后即为所求权重。
🚀2.3、一致性检验(特征值法使用)
在完成对各个因素的相对权重计算后,需要对计算后的判断矩阵进行一致性检验,其目的在于确保矩阵在逻辑上的一致性,避免由于不一致导致的评估结果偏差。
计算一致性指标
(
C
I
)
(CI)
(CI) 和随机一致性比例
(
C
R
)
(CR)
(CR),以检查比较矩阵的一致性。计算一致性指标
(
C
I
)
(CI)
(CI):
C
I
=
λ
max
−
n
n
−
1
CI = \frac{\lambda_{\max} - n}{n - 1}
CI=n−1λmax−n
其中,
λ
max
\lambda_{\max}
λmax是比较矩阵的特征值的最大值,
n
n
n 是因素的数量。如果
(
C
R
)
(CR)
(CR) 小于或等于 0.1,则认为判断矩阵具有较好的一致性,可以接受;否则,则认为该矩阵在逻辑关系上存在问题,需要重新调整。
查找对应的平均随机一致性指标
(
R
I
)
(RI)
(RI),如表所示。
平均随机一致性指标 RI 表
n | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
---|---|---|---|---|---|---|---|---|---|---|
RI | 0 | 0 | 0.52 | 0.89 | 1.12 | 1.26 | 1.36 | 1.41 | 1.46 | 1.49 |
计算一致性比例
(
C
R
)
(CR)
(CR):
C
R
=
C
I
R
I
CR = \frac{CI}{RI}
CR=RICI如果
(
C
R
<
0.1
)
(CR < 0.1)
(CR<0.1),则可认为判断矩阵的一致性可以接受;否则需要对判断矩阵进行修正。
📚三、 案例分析
🚀3.1、基础案例
以下代码测试在Jupyter Notebook分块实现
📘3.1.1、特征值法
import numpy as np
A = np.array([ [1,1/3,1/4,1/5],
[3, 1, 3/4, 3/5],
[4,4/3,1,4/5],
[5,5/3,5/4,1]])
n=len(A) #获取指标个数
print(A)
RI=[0,0.58,0.90,1.12,1.24,1.32,1.41, 1.45,1.49,1.51]
R= np.linalg.matrix_rank(A) #求判断矩阵的秩
R
v,D=np.linalg.eig(A) #求判断矩阵的特征值和特征向量,V特征值,D特征向量.
print('特征值V:\n',v,'\n特征向量D:\n',D)
# list1 = list(v)
B= np.max(v) #最大特征值
index = np.argmax(v) #最大特征值对应的索引
C = D[:, index] #对应特征向量
print('最大特征值B:\n',B,'\n最大特征值对应特征向量:\n',C)
CI=(B-n)/(n-1) #计算一致性检验指标CI
CR=CI/RI[n]
if CR<0.10:
print("CI=",CI)
print("CR=",CR)
print('对比矩阵A通过一致性检验,各向量权重向量Q为:')
sum=np.sum(C)
Q=C/sum #特征向量标准化
print(Q) # 输出权重向量
else:
print('对比矩阵A未通过一致性检验,需对对比矩阵A重新构造')
📈3.1.2 、特征值法运行结果:
📘3.1.3、算数平均法
#算数平均法求
# 二维数组axis=0表示按列求和,axis=1表示按行求和
print(A.sum(axis=0))
print('归一化前的矩阵\n',A)
column_sum=A.sum(axis=0)
A_normalized = A/column_sum
# 输出归一化后的矩阵
print('归一化后的矩阵\n',A_normalized)
print('归一化后的矩阵的行和\n',A_normalized.sum(axis=1))
# 计算加权平均值
weighted_average = A_normalized.sum(axis=1)/A.shape[0]
# 输出加权平均值
print('加权平均值\n',weighted_average)
📈3.1.4、算数平均法运行结果:
📘3.1.5、几何平均法
#几何平均法求权重
A_dot_0=np.prod(A, axis=1)
A_dot_0
# 指定要开的次方数
n = len(A)
# 对每个元素进行 n 次方运算
result = np.power(A_dot_0, 1/n)
result_sum=np.sum(result)
result_normal=result/result_sum
result_normal
📈3.1.5、几何平均法运行结果
🚀3.2 、进阶案例
📄3.2.1、题目
题目要求:通过搜集相关数据,对比国内外市场前景的技术实力,建立商业云服务能力评估系统,对华为,阿里巴巴,亚马逊,谷歌和微软几个大型互联网公司的云服务能力进行评估,分别比较各方面性能的优劣。
🎉3.2.2、分析和结果展示:
首先,选取了通信服务、基础设施服务、平台服务、软件服务和监控服务作为一级指标,并将这些一级指标进一步细化为多个二级指标。接着,根据互联网公开数据,采用专家评分法对不同互联网公司的各项服务进行量化评分。通过层次分析法(AHP
),综合考虑各级指标的重要性,计算得到复合权重,并据此计算出每个公司的得分情况。最终,基于得分,对不同互联网公司的云服务能力进行评估。结果显示,得分最高的三家公司分别是华为(0.227)、亚马逊(0.221)和阿里巴巴(0.205);谷歌和微软的得分分别为0.184和0.165,与前三家公司仍有一定差距。
层级关系:
结果:
📘3.2.3、代码展示
以下代码测试在Jupyter Notebook分块实现
import pandas as pd
import numpy as np
import math
#求解5个服务的权重
score1= np.array([
[8, 7, 9, 9, 8], # 通信质量
[8, 7, 10, 9, 9], # 安全性
[8, 8, 10, 9, 9], # 可用性
[7, 8, 6, 8, 7] # 成本效益
])
score2=np.array([
[8, 8, 10, 9, 9], # 计算能力
[8, 8, 10, 9, 9], # 存储能力
[8, 7, 10, 9, 9], # 网络性能
[8, 8, 10, 9, 9], # 可扩展性
[7, 8, 6, 8, 7] # 成本效益
])
score3=np.array([
[8, 8, 9, 8, 9], # 硬件性能
[8, 7, 10, 9, 9], # 软件支持
[8, 8, 10, 9, 9], # 安全性
[8, 8, 10, 9, 9], # 可用性
[7, 8, 6, 8, 7] # 成本效益
])
score4=np.array([
[8, 8, 10, 9, 9], # 功能丰富度
[8, 7, 8, 9, 9], # 用户体验
[8, 8, 10, 9, 9], # 安全性
[8, 8, 10, 9, 9], # 可用性
[7, 8, 6, 8, 7] # 成本效益
])
score5=np.array([
[8, 8, 10, 9, 9], # 监控覆盖范围
[8, 8, 10, 9, 9], # 实时性
[8, 8, 10, 9, 9], # 安全性
[8, 8, 10, 9, 9], # 可用性
[7, 8, 6, 8, 7] # 成本效益
])
q1_contrast_1 = np.array([
[1, 1, 1.2, 1.5, 1.7],
[1, 1, 1.1, 1.3, 1.5],
[0.83, 0.91, 1, 1.2, 1.4],
[0.67, 0.77, 0.83, 1, 1.2],
[0.59, 0.67, 0.71, 0.83, 1]
])
q2_contrast_1 = np.array([
[1, 1.2, 1.3, 1.4, 1.5],
[0.83, 1, 1.1, 1.2, 1.3],
[0.77, 0.91, 1, 1.1, 1.2],
[0.71, 0.83, 0.91, 1, 1.1],
[0.67, 0.77, 0.83, 0.91, 1]
])
q3_contrast_1 = np.array([
[1, 1.1, 1.2, 1.3, 1.4],
[0.91, 1, 1.1, 1.2, 1.3],
[0.83, 0.91, 1, 1.1, 1.2],
[0.77, 0.83, 0.91, 1, 1.1],
[0.71, 0.77, 0.83, 0.91, 1]
])
q4_contrast_1 = np.array([
[1, 1.1, 1.3, 1.4, 1.5],
[0.91, 1, 1.2, 1.3, 1.4],
[0.77, 0.83, 1, 1.1, 1.2],
[0.71, 0.77, 0.91, 1, 1.1],
[0.67, 0.71, 0.83, 0.91, 1]
])
q5_contrast_1 = np.array([
[1, 1.2, 1.3, 1.4, 1.5],
[0.83, 1, 1.1, 1.2, 1.3],
[0.77, 0.91, 1, 1.1, 1.2],
[0.71, 0.83, 0.91, 1, 1.1],
[0.67, 0.77, 0.83, 0.91, 1]
])
q1_contrast_2=np.array([[1,2,2,3],
[0.5,1,2,2],
[0.5,0.5,1,2],
[0.33,0.5,0.5,1]])
q2_contrast_2=np.array([[1,2,2,2,3],
[0.5,1,1.5,2,2.5],
[0.5,0.67,1,2,2],
[0.5,0.5,0.5,1,2],
[0.33,0.4,0.5,0.5,1]])
q3_contrast_2=np.array([[1,2,2,3,3],
[0.5,1,1.5,2,2.5],
[0.5,1,1.5,2,2.5],
[0.33,0.5,0.67,1,1.5],
[0.33,0.4,0.5,0.67,1]])
q4_contrast_2=np.array([[1,2,2,3,3],
[0.5,1,1.5,2,2.5],
[0.5,0.67,1,1.5,2],
[0.33,0.5,0.67,1,1.5],
[0.33,0.4,0.5,0.67,1]])
q5_contrast_2=np.array([[1,2,2,3,3],
[0.5,1,1.5,2,2.5],
[0.5,0.67,1,1.5,2],
[0.33,0.5,0.67,1,1.5],
[0.33,0.4,0.5,0.67,1]
])
variables_1=[ q1_contrast_1,q2_contrast_1,q3_contrast_1, q4_contrast_1,q5_contrast_1]
variables_2 = [ q1_contrast_2,q2_contrast_2,q3_contrast_2, q4_contrast_2,q5_contrast_2]
#求解一级指标权重
q_1_norm=[]
result_1_normal=[]
for i,variables in enumerate(variables_1):
i=i
q_1_norm.append(variables / variables.sum(axis=0))
n=len(q_1_norm[i])
RI=[0,0.58,0.90,1.12,1.24,1.32,1.41, 1.45,1.49,1.51]
R= np.linalg.matrix_rank(q_1_norm[i]) #求判断矩阵的秩
# print(i)
v,D=np.linalg.eig(q_1_norm[i]) #求判断矩阵的特征值和特征向量,V特征值,D特征向量.
# print('特征值V:\n',v,'\n特征向量D:\n',D)
# list1 = list(v)
B= np.max(v) #最大特征值
index = np.argmax(v) #最大特征值对应的索引
C = D[:, index] #对应特征向量
# print('最大特征值B:\n',B,'\n最大特征值对应特征向量:\n',C)
CI=(B-n)/(n-1) #计算一致性检验指标CI
CR=CI/RI[n]
if CR<0.10:
print("CI=",CI)
print("CR=",CR)
print('对比矩阵A通过一致性检验,各向量权重向量Q为:')
sum=np.sum(C)
Q=C/sum #特征向量标准化
print(Q) # 输出权重向量
else:
print('对比矩阵A未通过一致性检验,需对对比矩阵A重新构造')
# 几何平均法求权重
A_dot_0=np.prod(q_1_norm[i], axis=1)
A_dot_0
# 指定要开的次方数
n = len(q_1_norm[i])
# 对每个元素进行 n 次方运算
result = np.power(A_dot_0, 1/n)
result_sum=np.sum(result)
result_1_normal.append(result/result_sum)
#求解二级指标权重
q_2_norm=[]
result_2_normal=[]
for i,variables in enumerate(variables_2):
i=i
q_2_norm.append(variables / variables.sum(axis=0))
n=len(q_2_norm[i])
RI=[0,0.58,0.90,1.12,1.24,1.32,1.41, 1.45,1.49,1.51]
R= np.linalg.matrix_rank(q_2_norm[i]) #求判断矩阵的秩
# print(i)
v,D=np.linalg.eig(q_2_norm[i]) #求判断矩阵的特征值和特征向量,V特征值,D特征向量.
# print('特征值V:\n',v,'\n特征向量D:\n',D)
# list1 = list(v)
B= np.max(v) #最大特征值
index = np.argmax(v) #最大特征值对应的索引
C = D[:, index] #对应特征向量
# print('最大特征值B:\n',B,'\n最大特征值对应特征向量:\n',C)
CI=(B-n)/(n-1) #计算一致性检验指标CI
CR=CI/RI[n]
# if CR<0.10:
# print("CI=",CI)
# print("CR=",CR)
# print('对比矩阵A通过一致性检验,各向量权重向量Q为:')
# sum=np.sum(C)
# Q=C/sum #特征向量标准化
# print(Q) # 输出权重向量
# else:
# print('对比矩阵A未通过一致性检验,需对对比矩阵A重新构造')
# 几何平均法求权重
A_dot_0=np.prod(q_2_norm[i], axis=1)
# 指定要开的次方数
# n = len(q_2_norm[i])
# 对每个元素进行 n 次方运算
result = np.power(A_dot_0, 1/n)
result_sum=np.sum(result)
result_2_normal.append(result/result_sum)
result_1_normal=np.array(result_1_normal).reshape(5,5)
result_1_normal=result_1_normal.mean(axis=0)
print('一级指标权重为:\n',result_1_normal)
print('二级指标权重为:\n',result_2_normal)
# result_1_normal=result_1_normal/result_1_normal.sum(axis=0)
result_1_normal
📈运行结果:
import numpy as np
score=[score1,score2,score3,score4,score5]
weighted_2=[]
# 计算二级得分
for i in range(1,6):
result_2_normal[i-1] = result_2_normal[i-1].reshape(-1, 1)
# weights = result_2_normal.reshape(,1)
weighted_q1 = result_2_normal[i-1] * score[i-1]
weighted_2.append(weighted_q1.sum(axis=0) )
# print('二级指标各个权重的得分:\n',weighted_q1)
#计算综合得分
score_final=weighted_q1*result_1_normal
companies = ['Huawei', 'Alibaba', 'AWS', 'Google', 'Microsoft']
services = ['通信服务', '基础设施服务', '平台服务', '软件服务', '监控服务']
scores_1 = pd.DataFrame(score_final, columns=companies, index=services )
print('一级指标各个权重的得分:\n',scores_1)
score_final=score_final.sum(axis=0)
# List of companies
# Convert array to dictionary
scores_dict = dict(zip(companies, score_final))
# Dataframe_scores = pd.DataFrame(scores_dict)
# Dataframe_scores
Dataframe_scores = pd.DataFrame(list(scores_dict.items()), columns=['Company', 'Score'])
Dataframe_scores=Dataframe_scores.sort_values(by='Score', ascending=False)
Dataframe_scores=Dataframe_scores
📈运行结果:
Dataframe_scores['Score']=Dataframe_scores['Score']/Dataframe_scores['Score'].sum()
Dataframe_scores
📈运行结果:
import seaborn as sns
import matplotlib.pyplot as plt
import matplotlib
from matplotlib import font_manager
matplotlib.rc("font",family='SimHei',weight='normal',)
# sns.set_theme(style='white',palette="muted", context="talk")
colors =sns.choose_colorbrewer_palette(data_type='qualitative')
# colors=sns.choose_cubehelix_palette()
# 绘制条形图
sns.set_context("talk")
# ci', 'pi', 'se', 'sd'
sns.barplot(x="Company", y="Score", data=Dataframe_scores,palette=colors,errorbar='ci', capsize=0.1)
x = np.arange(len(Dataframe_scores))
y = Dataframe_scores['Score']
plt.ylim(0, 0.25)
# plt.plot(x, y, marker='o', linestyle='--', color=colors[1], label='趋势线')
plt.title("不同公司云服务能力总得分对比")
plt.xlabel("公司")
plt.ylabel("总得分")
plt.show()
# help(sns.color_palette)
📈运行结果:
😊总结感想😊:
最后的进阶案例是2024年备战全国大学生数学建模竞赛的一道赛前练习题,时间应该在8月22日左右,写了这篇博客来进行技术总结,的确总结的挺晚。记得当时和队友找了半天资料,GPT也是参考了一堆链接,在此要感谢我的赵大队友(找资料大王😂),和张大锋哥(论文手😊),同时也要感谢一些B站的up主们,他们的视频对我的学习建模之路很有帮助。后面虽然论文没交上,19.40左右官网崩溃了,就差点,可惜了,不过事已至此,总结经验,继续前进。😊😊😊💖💖💖