AHP层次分析法与python代码讲解(处理论文、建模)

article/2025/9/12 5:02:08

目录

AHP是啥

题目 

①构建阶梯层次结构

②构建判断矩阵

④综合算术平均法 、几何平均法、特征值法求权重 

方法1:算术平均法求权重

一般步骤 

表达式解释

代码实现

方法2:几何平均法求权重

一般步骤 

表达式解释

代码实现

方法3:特征值法求权重 

代码实现  

求综合平均权重

③对判断矩阵进行一致性检验 

一致性指标CI计算

一致性比例CR计算

对代码的小小的展望:

⑤填充矩阵,得出结果 

AHP扩展知识 

个人拙见


眼尖的人会发现,目录中③和④是反的。 

AHP是啥

        层次分析法(analytic hierarchy process)简称AHP。是建模比赛中比较基础的模型之一,其主要解决评价类的问题,毕业论文中也经常能见到,可用于绩效评价。如选择哪种方案最好,哪位员工表现最好等。

学习本文后,你将会对AHP有个大致了解,然后你会掌握Python代码计算AHP模型

        该方法本质就是把一个决策问题根据评价的标准将其分为多层次结构,这些层次按照一定的关联关系构成自上而下的一种阶梯构造,再根据最底下的层次到高层次通过两两进行对比得出各个因素的权重,权重最大的就是这些方案中最好的方案或因素。

        本文借鉴了数学建模清风老师的课件与思路,如果大家发现文章中有不正确的地方,欢迎指正,也可以点击链接查看清风老师视频讲解:清风数学建模:https://www.bilibili.com/video/BV1DW411s7wi

AHP 的主要计算可分为五个过程 

构建阶梯层次结构
构建判断矩阵
对判断矩阵进行一致性检验
综合算术平均法 、几何平均法、特征值法求权重

填充矩阵,得出结果

后续会逐一讲到

题目 

  小明同学想出去旅游。在查阅了网上的攻略后,他初步选择了苏杭北戴河桂林三地之一作为目标景点。请你确定评价指标、形成评价体系来为小明同学选择最佳的方案。 

首要目的:对于评价类问题,首先需要明确以下三个问题:

①我们评价的目标是什么?

        答:为小明同学选择最佳的旅游景点。
②评价的准则或者说指标是什么?(我们根据什么东西来评价好坏)  

        题目没给相关数据,需要我们确定。

(一般而言,①③这两个问题的答案是显而易见的,问题②的答案需要我们根据题目中的背景材料、常识以及网上搜寻到的参考资料进行结合,从中筛选出最合适的指标)

        答:这里我们选择了景色、花费、居住、饮食、交通。
③我们为了达到这个目标有哪几种可选的方案 ?   

        答:三种,分别是去苏杭、去北戴河和去桂林。

构建阶梯层次结构

有了以上内容,我们就可以构建阶梯层次结构

在这里插入图片描述

下图为我们最终需要得出的结果图的样子,对于其中内容的填写,就需要使用到AHP方法了。

在这里插入图片描述

  • 其中,蓝色一列代表景色、花费、居住、饮食以及交通的权重,加和为1(有时候加起来不是1是因为四舍五入的原因)。(实际上就是准则层关于上一层目标层的重要性)
  • 然后同一颜色每一横行,就是三种方案相对于准则层的重要性。


构建判断矩阵

        建立阶梯层次结构模型时,有必要清楚模型中各个因素之间的联系, 这中联系在 AHP 中要用矩阵法来表现出来,就是对各个指标之间采用 两两比较 , 用 cij 表示元素 i 对元素 j 的注重程度比较值,以数字从 1 9 还有它的倒数作为比较标准,然后对评价指标进行打分排列,判断矩阵就是在这个基础上建立得出的。

        矩阵个数确定 :由上文所讲内容可知得到这个判断矩阵实际上要分别得出准则层关于目标层的一组权重向量,方案层关于准则层的五组权重向量,实际上我们就需要构造出一个准则层关于目标层的判断矩阵以及五个方案层关于准则层的矩阵,一共六个判断矩阵(如下)。
 

 

根据以上这个表格,我们去寻找专家填写,或者根据上述说的,根据理论基础来填写,得到了下面这个判断矩阵。

在这里插入图片描述

在这里插入图片描述在这里插入图片描述 

观察一下:上面这个判断矩阵有如下特点

①aij 表示的意义是,与指标j相比, i的重要程度。(注意i是行j是列,笔者经常搞混)

②主对角线元素为1原因:当i= j时,两个指标相同,因此同等重要记为1

③aj >0 且满足aij = 1/aji,也就是 aij × aji = 1 (我们称满足这一条件的矩阵为正互反矩阵)


综合算术平均法 、几何平均法、特征值法求权重 

填充权重矩阵,根据矩阵计算得分,得出结果。
这里我们先进行填充方案层关于准则层的五组权重向量

计算权重的方法有三种:

①算数平均法求权重

②几何平均法求权重

特征值法求权重

一般情况下:第三种特征值法求权重是最常用的,但是建议可以综合三种方法来求得一个综合的权重向量。

下面拿下面这个判断矩阵进行说明:
在这里插入图片描述


方法1:算术平均法求权重

一般步骤 

第一步: 将判断矩阵按照列归一化(每个元素除以其所在列的和,如1/(1+0.5+0.2)=0.5882)

在这里插入图片描述
第二步: 将归一化的列相加(按行求和)

在这里插入图片描述 
第三步: 将相加后得到的向量中的每个元素除以 n 即可得到权重向量

在这里插入图片描述

表达式解释

代码实现

import numpy as np
from numpy import linalg
# np.set_printoptions(precision=4)
'''算术平均法权重'''
def arithmetic_mean(a):n = len(a)b = sum(a)print('b:', b)# 归一化处理normal_a = a/bprint("算术平均法权重-归一化处理:")print(normal_a)average_weight = []for i in range(n):s = sum(normal_a[i])print("第{}行求和 ".format(i+1), s)# 平均权重average_weight.append(s/n)# print(average_weight)print('算术平均法权重:')print(np.array(average_weight))return np.array(average_weight)

结果如下: 

讲解

①如果你想全篇设置四位小数点,在开头加上这个

np.set_printoptions(precision=4)

  

②对二维数组使用sum函数,最终形成的是一个包含每列的和的数组。

将数组a除以该数组,就得到了归一化的数组。 

③代码for循环中进行了上述步骤二和三,先对每行求和,然后除以n,得到了权重。


方法2:几何平均法求权重

一般步骤 

第一步: 将A的元素按照行相乘得到一个新的列向量

第二步: 将新的向量的每个分量开n次方

第三步: 对该列向量进行归一化即可得到权重向量

表达式解释

代码实现

'''几何平均法求权重'''
def geometric_mean(a):n = len(a)# 1表示按照行相乘,得到一个新的列向量b = np.prod(a, 1)print(b)c = pow(b, 1/n)print(c)# 归一化处理average_weight = c/sum(c)print('几何平均法权重:')print(average_weight)return average_weight

如图,这个[10,1,0.1] 是列向量

c为开n次方的数组。

在这里插入图片描述

结果一样


方法3:特征值法求权重 

线性代数学习之特征值与特征向量

        在了解 这个之前,你得大致了解一下什么是特征值,特征向量,最大特征值(上文建议好好看看前半部分

对于一个矩阵A来说,我们对这样的向量比较感兴趣:在矩阵A的转换下得到的结果向量其方向并没有发生改变,只不过结果向量变为某一个向量的的常数倍了

数学上这样表示:

其中λ称为A的特征值(eigenvalue)

而u向量称为A对应于λ的特征向量(eigenvector)

代码实现  

'''特征值法求权重'''
def eigenvalue(a):w, v = np.linalg.eig(a)for i in range(len(w)):print('特征值', a[i], '特征向量', v[:, i])index = np.argmax(w)w_max = np.real(w[index])vector = v[:, index]vector_final = np.transpose(np.real(vector))print('最大特征值', w_max, '对应特征向量', vector_final)normalized_weight = vector_final/sum(vector_final)print('***归一化处理后:', normalized_weight)return w_max, normalized_weight

np.linalg.eig() 就是用来计算正方形数组的特征值与特征向量的 。

上图是官方文档对于w和v的定义的,看不懂没事,我将其打印输出后,你们就明白了 

这里的w是每一行的特征值所组成的数组,这里的v是归一化后的特征向量

np.argmax(w)

上面代码用于返回最大值的索引,

np.real()

上面代码用于返回复杂参数的实部 

vector = v[:, index]

这里涉及到[:,] 的使用,

vector = v[:, 0]表示取数组的第0列
vector = v[:, 1]表示取数组的第1列
vector = v[0,:]表示取数组的第0行
vector = v[1,:]表示取数组的第1行

归纳总结可以知道冒号逗号数字的顺序表示取列,数字逗号冒号的顺序表示取行

因此最初代码表示按照最大特征值的索引取列。 


对最大特征值取小数点四位可以替换成下面的代码

w_max = round(np.real(w[index]),4)

最终将最大特征值对应的特征向量归一化就得出了权重。

求综合平均权重

'''综合平均权重'''
def average_Weight(a):am = arithmetic_mean(a)gm = geometric_mean(a)ev = eigenvalue(a)[1]aw = np.array([am, gm, ev])print(aw)final_weight = sum(aw)/3print(final_weight)return final_weight

将上述三种方法得到的权重经过综合,得到了最终的权重 

上面代码先获取三种方法的权重,放到数组中,最终计算平均权重。

对判断矩阵进行一致性检验 

返回上面说的(重点) 

你在求权重前填写的矩阵,也叫做判断矩阵。其首先是一个正互反矩阵

(aj >0 且满足 aij × aji = 1)

这里很好理解,例如:由于互相影响,i对j是5,j对i就是1/5,而不是1/4或其他数字。

'''判断正互反矩阵'''
def reciprocal_matrix_judge(a):print(a)n = len(a)b = 0for j in range(n):for i in range(n):if a[:, j][i] * a[j, :][i] == 1:b += 1if b == n*n:print("该矩阵是正互反矩阵!\n")return Trueelse:print("该矩阵不是正互反矩阵!\n")return False

        这里笔者使用自己的理解写的python判断正互反矩阵的代码(网上貌似没找到有人写过),由于笔者对数组这些不太熟,就不是按照定义上判断aij是否等于1/aji而是采用判断aij与aji乘积为1的个数,如果刚好为数组元素的个数,也是数组行数或者列数的平方(因为两两比较,所以是个方阵)

        当然,期待有人使用定义或者其他更好的方法进行判断正互反矩阵。


是正互反矩阵还不够,还需要进行一致性检验。 

考虑:
在这里插入图片描述

假设我们填写的判断矩阵是这个样子(下面括号中的是标度

苏杭(2)比北戴河(1)景色好一点

苏杭(1)和桂林(1)景色一样好

这里我们就可以得出桂林北戴河景色好一点,可是图上面的内容表达的意思是

北戴河(2)比桂林(1)景色好一点

由上可以看出,出现了矛盾

从这里就得提出一个概念叫做一致矩阵,它在正互反矩阵性质的基础上没有以上的矛盾,可以说:一致矩阵是正互反矩阵的特例。
将上面的矩阵进行改良,得到一致矩阵:

在这里插入图片描述

它比正互反矩阵多出两个性质:

①     aij = i的重要程度 / j的重要程度,

        ajk = j的重要程度 / k的重要程度,

        aik = i的重要程度 / k的重要程度 = aij × ajk。
②    矩阵各行(各列)之间成倍数关系。
  我们进行构造矩阵时难免会出现矛盾,即不容易构造出一致性矩阵,但是我们可以向一致性矩阵靠拢,只要这个差距(CR)不超过一个范围(0.1)那么这个判断矩阵也是可以使用的。这个判断差距的过程叫做一致性检验。

证明过程如下:

一致性检验原理: 检验我们构造的判断矩阵和一致矩阵是否有太大的差别。

 

上图为清风老师使用matlab计算a值变化-最大特征值变化图 

总而言之,判断矩阵越不一致时,最大特征值与 n 相差就越大。 


接下来我们讲如何计算CI,CR

一致性指标CI计算

公式如下 

代码如下:

'''CI计算'''
def CI_calc(a):n = len(a)λ_max = eigenvalue(a)[0]print(λ_max)CI = (λ_max-n)/(n-1)print('CI:', CI)return CI

eigenvalue()是上文提到的特征值法求权重,由于我们需要 λ_max(最大特征值),其是eigenvalue()中第一个返回的w_max。然后使用CI的计算公式计算即可

结果如下

根据n查找对应的平均随机一致性指标 RI

一致性比例CR计算

公式如下 

代码如下:

'''CR计算'''
def CR_calc(a):RI = np.array([0, 0, 0.52, 0.89, 1.12, 1.26, 1.36, 1.41,1.46, 1.49, 1.52, 1.54, 1.56, 1.58, 1.59])n = len(a)CI = CI_calc(a)CR = CI/RI[n-1]print('CR:', CR)if CR < 0.1:print("一致性检验通过!\n")return Trueelse:print("一致性检验失败,请修改!")return False

首先将RI以数组的形式输入其中,然后构建公式求RI的值,判断其是否小于0.1.

结果如下:

发现一致性检验通过。这样就说明构建的判断矩阵是可行的。

主函数

if __name__ == '__main__':a = np.array([[1, 2, 5],[1 / 2, 1, 2],[1 / 5, 1 / 2, 1]])rmj = reciprocal_matrix_judge(a)if rmj:if CR_calc(a):average_Weight(a)

结果如下(有些内容不需要的可以把print()打印给注释掉) 

最后一张图的最后一行就是综合权重。

对代码的小小的展望:

        这里笔者使用的print()函数较多,运行CI_calc()CR_calc() 函数时候,都会调用eigenvalue()函数,就会重复打印其中的特征值和对应的特征向量,这里可以优化

填充结果

 清风老师是使用特征值法求的权重,得出最终的权重矩阵(这里我就直接使用清风老师的内容了,不再去单独做综合三种方法得到的权重的excel)

 

填充矩阵,得出结果 

计算得分,得出最终结果

        苏杭得分:指标权重×苏杭与其他两种方案中的权重,即前两列相乘:
0.5954×0.2636+0.0819×0.4758+0.4286×0.0538+0.6337×0.0981+0.1667×0.1087=0.299
同理:北戴河得分为0.245,桂林得分为0.455。

因此最终选择桂林


AHP扩展知识 

        1、评价的决策层不能太多,太多的话n会很大,判断矩阵和一致矩阵差异可能会很大。因为平均随机一致性指标 RI 的表格中 n 最多是15,因此应该根据实际情况选择是否应用此方法。
        2、如果决策层中指标的数据是已知的,那么层次分析法不容易将这些已知数据应用在其中。如拿上面的例题举例:如果已知景色 、花费、居住、饮食以及交通在三个旅游景点的一些数据,那么如何将这些数据转化为构造判断矩阵的依据,只能为其提供一定的文字说明,而不容易将数据应用到其中。
        3、在实际建模中,判断矩阵的数值都是人为填的,具有一定的主观性存在,这时应该搜寻相应的数据让人信服,不能空口无凭。

个人拙见

        ①关于AHP层次分析法就讲到这里,希望大家能多看几遍,可能后续建模或者论文中会涉及到,就我个人认为,虽然是专家填的判断矩阵,也使用客观的一致性检验,该模型应该算是主观的一类评价类模型。

        ②AHP层次分析法涉及到线性代数的一些内容,而其他的评价类模型,如DEA数据包络方法,其还涉及到运筹学相关知识(对偶问题)。

以上内容有不懂的,可以通过文末联系我。


http://chatgpt.dhexx.cn/article/4mlW3Xia.shtml

相关文章

用人话讲明白AHP层次分析法(非常详细原理+简单工具实现)

用人话讲明白AHP层次分析法&#xff08;非常详细原理简单工具实现&#xff09; 文章目录 目录 1、前言与算法简述 2、AHP层次分析法过程 2.1 构建层次评价模型 2.2 构造判断矩阵 2.3 层次单排序与一致性检验 2.3.1 层次单排序 2.3.2 求解最大特征根与CI值 2.3.3 根据…

微信公众号如何设置开发者密码(APPSecret)?

1.电脑端登录微信公众号&#xff0c;在左侧的导航栏找到</>开发里的“基本配置”&#xff0c;点击进入 2.基本配置页面如下 3.点击开发者密码&#xff08;APPSecret&#xff09;启用按钮 4.有弹窗提示用管理员的微信号扫码后才能操作 5.手机端管理员微信扫码&#xff0c;…

iOS “[App] if we're in the real pre-commit handler we can't actually add any new fences due

最近运行APP&#xff0c;发现了这个问题&#xff0c;本着宁可错看&#xff0c;不可放过的原则&#xff0c;上stackoverFlow学习了一下&#xff1a; 链接&#xff1a;http://stackoverflow.com/questions/38458170/ios-10-app-if-were-in-the-real-pre-commit-handler-we-cant-…

微信小程序重置AppSecret 之后需要做的事情

现在appSecret是密文的如果保存不妥当 需要管理账号用重置 具体位置如下&#xff1a; 点击重置之后 2小时之内程序不会出现任何错误 但是2小时之后 当你打开你的微信小程序之后就会发现有很多接口出现如下错误&#xff1a; invalid appsecret 这个时候只需要联系后端同学 将之…

如何查看小程序的APPID和AppSecret

小程序APPID可以在手机上打开小程序后&#xff0c;点击右上角三点&#xff1a; 然后点击中间位置的小程序名称&#xff0c;进入小程序介绍页面&#xff1a; 点击“更多资料”后&#xff0c;进入页面就可以看到上方有APPID&#xff1a; 另一种方法&#xff1a; 在微信公众平台登…

微信小程序——查看AppId和AppSecret

1.登录微信公众平台&#xff1a;https://mp.weixin.qq.com/ 2.点击开发管理--------------》开发设置&#xff1a;

uniapp开发微信小程序解决上线:审核问题“包含明文的AppSecret,存在泄漏的安全风险“以及上线之后接口请求失败

微信小程序上线审核提示&#xff1a;审核问题“包含明文的AppSecret&#xff0c;存在泄漏的安全风险“ 解决&#xff1a; 原因是我在登录通过uni.login获取到code然后用code获取openid时用到了AppSecret&#xff0c;因为之前后端没空写接口我就在前端自己获取的openid&#xff…

通过appId和appSecret生成accessToken访问api后端接口(接口授权)

功能点 &#xff08;1&#xff09;申请获取appId和appSecret &#xff08;2&#xff09;通过appId和appSecret获取accessToken &#xff08;3&#xff09;mysql和redis进行key-value键值对存储 &#xff08;4&#xff09;对需要的接口url进行请求地址拦截 效果图&#xff1a; &…

微信开发者之AppID和AppSecret举例子

-- 请不要为爱你的人流泪&#xff0c;因为爱你的人不会让你流泪&#xff01; 序 今天对这2东西做个相对全面的介绍&#xff0c;不一定深入&#xff0c;但是对实际开发还是很有必要的 我们在微信开发中总是会绕不开2个单词&#xff1a; AppID&#xff1a;开发者ID,有些叫AppK…

安全课堂|关于小程序AppSecret密钥泄露漏洞官方

原文链接:https://developers.weixin.qq.com/community/minihome/doc/0004a84fcb0bb0e89eddbaa5156401 安全课堂&#xff5c;关于小程序AppSecret密钥泄露漏洞官方 微信团队04-27 为进一步提升小程序的安全性和用户体验&#xff0c;目前平台对提审的小程序均需进行安全检测&…

【微信小程序】项目上线所需AppID、AppSecret和原始ID获取的逐步方法

一、简述 本文内容面向业务老师&#xff0c;通过详细的逐步方法&#xff0c;帮助对流程不熟悉的有微信小程序管理员权限的业务老师&#xff0c;通过微信公众平台&#xff0c;获得项目上线所需的AppID、AppSecret、原始ID&#xff0c;不熟悉流程的开发人员也可以阅读。 二、进…

微信小程序AppID、AppSecret如何获取

进入微信公众平台 https://mp.weixin.qq.com/ 获取AppID&#xff08;小程序ID&#xff09; 微信公众平台 - 开发 - 开发管理 - 开发设置 获取AppSecret 管理员用户&#xff0c;同AppID页面&#xff0c;点击“生成”&#xff0c;生成小程序秘钥 注意&#xff1a;尽量只生成一次&…

值得收藏!这 100 个 Python 实战小项目真棒!

学习 Python 会有这么一个阶段&#xff0c;太简单的程序看不上眼&#xff0c;复杂的开源项目又有点力不从心&#xff0c;这个时候&#xff0c;你就需要接触点简单的 Python 小项目来提升 Python 技能。 最近逛GitHub, 碰巧碰上有这样一个项目&#xff0c;收集了 100 个实用的 …

2022最新python100个实战练手项目,【附源码】,快来学习起来吧!

Python是目前最好的编程语言之一。由于其可读性和对初学者的友好性&#xff0c;已被广泛使用。那么要想学会并掌握Python&#xff0c;可以实战的练习项目是必不可少的。 接下来&#xff0c;我将给大家介绍20个非常实用的Python项目&#xff0c;帮助大家更好的学习Python。大家…

python爬虫实战小项目

本文所讲的爬虫实战属于基础、入门级别&#xff0c;使用的是python2.7实现的。 爬虫原理和思想 本项目实现的基本目标&#xff1a;在捧腹网中&#xff0c;把搞笑的图片都爬下来&#xff0c;注意不需要爬取头像的图片&#xff0c;同时&#xff0c;将图片命好名放在当前的img文件…

django项目实战基于Python实现的电影推荐系统

&#x1f496;&#x1f496;更多项目资源&#xff0c;最下方联系我们✨✨✨✨✨✨ 目录 Python项目介绍 资料获取 Python项目介绍 计算机毕业设计python毕设项目之django电影推荐系统-IT实战课堂_哔哩哔哩_bilibili计算机毕业设计python毕设项目之django电影推荐系统-IT实战…

给缺少Python项目实战经验的人

我们在学习过程中最容易犯的一个错误就是&#xff1a;看的多动手的少&#xff0c;特别是对于一些项目的开发学习就更少了&#xff01; 没有一个完整的项目开发过程&#xff0c;是不会对整个开发流程以及理论知识有牢固的认知的&#xff0c;对于怎样将所学的理论知识应用到实际…

Python项目实战 —— 淘宝用户行为分析

Python项目实战 Python项目实战 —— 0淘宝用户行为分析 一、背景 本数据集共有大约1200万条数据&#xff0c;数据为淘宝APP2014年11月18日至2014年12月18日的用户行为数据&#xff0c;字段分别是&#xff1a;user_id用户身份(已脱敏)、item_id商品ID(已脱敏)、behavior_type…

Python实战小项目

不是很稀饭《复联》嘛&#xff0c;看了《复联4》&#xff0c;就用50行Python代码做了这些&#xff1a; 视频展示&#xff1a;50行代码玩转《复仇者联盟》 教程地址&#xff1a;图片转字符画 相关教程地址&#xff1a;视频转字符动画 当然&#xff0c;这个仅仅是初学者的一个…

手把手教导实战Python Web项目

手把手教导实战Python Web项目 一、前言 Django是一个开放源代码的Web应用框架&#xff0c;由Python写成。采用了MVC的框架模式&#xff0c;即模型M&#xff0c;视图V和控制器C。Django的主要目的是简便、快速的开发数据库驱动的网站。它强调代码复用&#xff0c;多个组件可以很…