Python实现“层次分析法”及“自调节层次分析法”

假设我们遇到如下问题:
①对于M个方案,每个方案有N个属性,在已知各个方案每个属性值&&任意两个属性的重要程度的前提下,如何选择最优的方案?
②对于一个层级结构,在已知各底层指标相互之间的重要程度下,如何确定各底层指标对最高级指标的权值?
… …
此时,便可用层次分析法将我们的主观想法——“谁比谁重要”转换为客观度量——“权值”

层次分析法

层次分析法的基本思想是将复杂问题分为若干层次和若干因素,在同一层次的各要素之间简单地进行比较判断和计算,并评估每层评价指标对上一层评价指标的重要程度,确定因素权重,从而为选择最优方案提出依据。步骤如下:
(1)根据自己体系中的关联及隶属关系构建有层次的结构模型,一般分为三层,分别为最高层、中间层和最低层。

(2)构造判断矩阵
假设该层有n个评价指标u1, u2, …, un,设cij为ui相对于uj的重要程度,根据公式列出的1-9标度法,判断两两评价指标之间的重要性。

根据比较得出判断矩阵:
C=(cij)n*n其属性为cij>0, cji=1/cij,cii=1

(3)层次单排序:从下往上,对于每一层的每个判断矩阵,计算权向量和一致性检验。
计算矩阵C的最大特征根λmax及对应的特征向量(P1,P2,…, Pn)
一致性指标定义为:CI=λmax⁡−nn−1CI = \frac{{{\lambda _{\max }} - n}}{{n - 1}}CI=n−1λmax​−n​
CI(Consistency Ratio)称为一致性比例。CI=0时,具有完全一致性;CI接近于0,具有满意的一致性;CI越大,不一致性越严重。
一致性比率定义为:CR=CIRI<0.1{\rm{CR}} = \frac{{{\rm{CI}}}}{{{\rm{RI}}}} < 0.1CR=RICI​<0.1
其中RI称为随机性指标,参照表如下:

只有当CR<0.1,则认为该判断矩阵通过了一致性检验,即该矩阵自相矛盾产生的误差可忽略。将矩阵C最大特征根对应的特征向量元素作归一化处理,即可得到对应的权重集(C1,C2,…,Cn)。
(4)层次总排序
从上往下,依次计算每一层各指标对最上层指标的权值,以及每一层的综合一致性比率CR。

自调节层次分析法——赵中奇

由于层次分析法选用1-9标度构建判断矩阵,而大部分时候我们自己也不能很好度量重要性的程度,故赵中奇提出用-1,0,1三标度来构建判断矩阵。同时,自动调整判断矩阵,消除前后时刻主观比较重要性时的矛盾现象,即让矩阵变为一致性矩阵(CR=0)。构建并调整判断矩阵以及算权值向量的步骤如下:
(1)初始化m=1
a、确定比较矩阵C=(cij)n*n的第m行元素

b、划分指标集合Dm={j|j=m+1,…,n}为
Hm={j|cmj=-1,j∈Dm}、Mm={j|cmj=0,j∈Dm}与Lm={j|cmj=1,j∈Dm}
并构造集合为,其中×表示集合的笛卡尔积

c、若DLm、DMm、DHm全为空集,转d,否则令:

d、若m=n-1,转第二步,否则令m=m+1,转回a
(2)求比较矩阵C

(3)求B=(bij)n*n,其中

(4)求A=(aij)n*n的特征向量,作为各评价指标的相对权重值,其中:

实例分析

由于网上找到的代码大多只能算三层的体系,而且没有赵中奇论文中的自调节层次分析法代码。因此,自己写了一个可以计算超过3层的层次分析法和自调节层次分析法代码!

构建如下4层体系

层次分析法得到的权值

判断矩阵就不列出来了了,可以在代码里找到,得到第四层对A的权值条形图如下:

自调节层次分析法得到的权值

自调节层次分析法对高阶判断矩阵更有优势,而算低阶判断矩阵时的结果和层次分析法差不多。

代码

代码包括了层次分析法与自调节层次分析法的实例,运行的时候注释掉其中一个就行!

"""
Created on Tue Jan 26 10:12:30 2021
自适应层数的层次分析法求权值
@author: lw
"""import numpy as np
import itertools
import matplotlib.pyplot as plt#自适应层数的层次分析法
class AHP():'''注意:python中list与array运算不一样,严格按照格式输入!本层次分析法每个判断矩阵不得超过9阶,各判断矩阵必须是正互反矩阵FA_mx:下一层对上一层的判断矩阵集(包含多个三维数组,默认从目标层向方案层依次输入判断矩阵。同层的判断矩阵按顺序排列,且上层指标不共用下层指标)string:默认为'norm'(经典的层次分析法,需输入9标度判断矩阵),若为'auto'(自调节层次分析法,需输入3标度判断矩阵)'''#初始化函数def __init__(self,FA_mx,string='norm'):self.RI=np.array([0,0,0.58,0.9,1.12,1.24,1.32,1.41,1.45,1.49])   #平均随机一致性指标if string=='norm':self.FA_mx=FA_mx           #所有层级的判断矩阵elif string=='auto':self.FA_mx=[]for i in range(len(FA_mx)):temp=[] for j in range(len(FA_mx[i])):temp.append(self.preprocess(FA_mx[i][j]))self.FA_mx.append(temp)     #自调节层次分析法预处理后的所有层级的判断矩阵self.layer_num=len(FA_mx)   #层级数目self.w=[]                  #所有层级的权值向量self.CR=[]                 #所有层级的单排序一致性比例self.CI=[]                 #所有层级下每个矩阵的一致性指标self.RI_all=[]              #所有层级下每个矩阵的平均随机一致性指标self.CR_all=[]             #所有层级的总排序一致性比例self.w_all=[]              #所有层级指标对目标的权值#输入单个矩阵算权值并一致性检验(特征根法精确求解)def count_w(self,mx):n=mx.shape[0]eig_value, eigen_vectors=np.linalg.eig(mx)maxeig=np.max(eig_value)         #最大特征值maxindex=np.argmax(eig_value)    #最大特征值对应的特征向量eig_w=eigen_vectors[:,maxindex]/sum(eigen_vectors[:,maxindex])         #权值向量CI=(maxeig-n)/(n-1)RI=self.RI[n-1]if(n<=2 and CI==0):CR=0.0else:CR=CI/RIif(CR<0.1):return CI,RI,CR,list(eig_w.T)else:print('该%d阶矩阵一致性检验不通过,CR为%.3f'%(n,CR))return -1.0,-1.0,-1.0,-1.0#计算单层的所有权值与CRdef onelayer_up(self,onelayer_mx,index):num=len(onelayer_mx)           #该层矩阵个数CI_temp=[]RI_temp=[]CR_temp=[]w_temp=[]for i in range(num):CI,RI,CR,eig_w=self.count_w(onelayer_mx[i])if(CR>0.1):print('第%d层的第%d个矩阵未通过一致性检验'%(index,i+1))returnCI_temp.append(CI)RI_temp.append(RI)CR_temp.append(CR)w_temp.append(eig_w)self.CI.append(CI_temp)self.RI_all.append(RI_temp)self.CR.append(CR_temp)self.w.append(w_temp)#计算单层的总排序及该层总的一致性比例def alllayer_down(self):self.CR_all.append(self.CR[self.layer_num-1])self.w_all.append(self.w[self.layer_num-1])for i in range(self.layer_num-2,-1,-1):if(i==self.layer_num-2):temp=sum(self.w[self.layer_num-1],[])         #列表降维,扁平化处理,取上一层的权值向量CR_temp=[]w_temp=[]CR=sum(np.array(self.CI[i])*np.array(temp))/sum(np.array(self.RI_all[i])*np.array(temp))if(CR>0.1):print('第%d层的总排序未通过一致性检验'%(self.layer_num-i))returnfor j in range(len(self.w[i])):shu=temp[j]w_temp.append(list(shu*np.array(self.w[i][j])))temp=sum(w_temp,[])        #列表降维,扁平化处理,取上一层的总排序权值向量CR_temp.append(CR)self.CR_all.append(CR_temp)self.w_all.append(w_temp)return#计算所有层的权值与CR,层次总排序def run(self):for i in range(self.layer_num,0,-1):self.onelayer_up(self.FA_mx[i-1],i)self.alllayer_down()return#自调节层次分析法的矩阵预处理过程def preprocess(self,mx):temp=np.array(mx)n=temp.shape[0]for i in range(n-1):H=[j for j,x in enumerate(temp[i]) if j>i and x==-1]M=[j for j,x in enumerate(temp[i]) if j>i and x==0]L=[j for j,x in enumerate(temp[i]) if j>i and x==1]DL=sum([[i for i in itertools.product(H,M)],[i for i in itertools.product(H,L)],[i for i in itertools.product(M,L)]],[])DM=[i for i in itertools.product(M,M)]DH=sum([[i for i in itertools.product(L,H)],[i for i in itertools.product(M,H)],[i for i in itertools.product(L,M)]],[])if DL:for j in DL:if(j[0]<j[1] and i<j[0]):temp[int(j[0])][int(j[1])]=1if DM:for j in DM:if(j[0]<j[1] and i<j[0]):temp[int(j[0])][int(j[1])]=0if DH:for j in DH:if(j[0]<j[1] and i<j[0]):temp[int(j[0])][int(j[1])]=-1for i in range(n):for j in range(i+1,n):temp[j][i]=-temp[i][j]A=[]for i in range(n):atemp=[]for j in range(n):a0=0for k in range(n):a0+=temp[i][k]+temp[k][j]atemp.append(np.exp(a0/n))A.append(atemp)return np.array(A)   #%%测试函数
if __name__=='__main__' :'''# 层次分析法的经典9标度矩阵goal=[]             #第一层的全部判断矩阵goal.append(np.array([[1, 3],   [1/3 ,1]]))criteria1 = np.array([[1, 3],[1/3,1]])criteria2=np.array([[1, 1,3],[1,1,3],[1/3,1/3,1]])c_all=[criteria1,criteria2]   #第二层的全部判断矩阵sample1 = np.array([[1, 1], [1, 1]])sample2 = np.array([[1,1,1/3], [1,1,1/3],[3,3,1]])sample3 = np.array([[1, 1/3], [3, 1]])sample4 = np.array([[1,3,1], [1 / 3, 1, 1/3], [1,3, 1]])sample5=np.array([[1,3],[1/3 ,1]])sample_all=[sample1,sample2,sample3,sample4,sample5]  #第三层的全部判断矩阵FA_mx=[goal,c_all,sample_all]A1=AHP(FA_mx)     #经典层次分析法A1.run()a=A1.CR           #层次单排序的一致性比例(从下往上)b=A1.w            #层次单排序的权值(从下往上)c=A1.CR_all       #层次总排序的一致性比例(从上往下)d=A1.w_all        #层次总排序的权值(从上往下)e=sum(d[len(d)-1],[])       #底层指标对目标层的权值#可视化plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falsename=['D1','D2','D3','D4','D5','D6','D7','D8','D9','D10','D11','D12']plt.figure()plt.bar(name,e)for i,j in enumerate(e):plt.text(i,j+0.005,'%.4f'%(np.abs(j)),ha='center',va='top')plt.title('底层指标对A的权值')plt.show()'''#自调节层次分析法的3标度矩阵(求在线体系的权值)goal=[]             #第一层的全部判断矩阵goal.append(np.array([[0, 1],   [-1,0]]))criteria1 = np.array([[0, 1],[-1,0]])criteria2=np.array([[0, 0,1],[0,0,1],[-1,-1,0]])c_all=[criteria1,criteria2]   #第二层的全部判断矩阵sample1 = np.array([[0, 0], [0, 0]])sample2 = np.array([[0,0,-1], [0,0,-1],[1,1,0]])sample3 = np.array([[0, -1], [1, 0]])sample4 = np.array([[0,1,0], [-1, 0,-1], [0,1,0]])sample5=np.array([[0,1],[-1 ,0]])sample_all=[sample1,sample2,sample3,sample4,sample5]  #第三层的全部判断矩阵FA_mx=[goal,c_all,sample_all]A1=AHP(FA_mx,'auto')     #经典层次分析法A1.run()a=A1.CR           #层次单排序的一致性比例(从下往上)b=A1.w            #层次单排序的权值(从下往上)c=A1.CR_all       #层次总排序的一致性比例(从上往下)d=A1.w_all        #层次总排序的权值(从上往下)e=sum(d[len(d)-1],[])       #底层指标对目标层的权值#可视化plt.rcParams['font.sans-serif'] = ['SimHei']plt.rcParams['axes.unicode_minus'] = Falsename=['D1','D2','D3','D4','D5','D6','D7','D8','D9','D10','D11','D12']plt.figure()plt.bar(name,e)for i,j in enumerate(e):plt.text(i,j+0.005,'%.4f'%(np.abs(j)),ha='center',va='top')plt.title('底层指标对A的权值')plt.show()

Python实现“层次分析法”及“自调节层次分析法”相关推荐

  1. python倾向匹配得分_数据分析36计(九):倾向得分匹配法(PSM)量化评估效果分析

    1. 因果推断介绍 如今量化策略实施的效果评估变得越来越重要,数据驱动产品和运营.业务等各方的理念越来越受到重视.如今这方面流行的方法除了实验方法AB testing外,就是因果推断中的各种观察研究方 ...

  2. 原理+代码|详解层次聚类及Python实现/层次树怎么看/如何从层次树中查看聚类过程(附源数据)

    前言 聚类分析是研究分类问题的分析方法,是洞察用户偏好和做用户画像的利器之一.聚类分析的方法非常多,能够理解经典又最基础的聚类方法 -- 层次聚类法(系统聚类) 的基本原理并将代码用于实际的业务案例是 ...

  3. R语言分析蛋白质组学数据:飞行时间质谱(MALDI-TOF)法、峰值检测、多光谱比较...

    全文链接:http://tecdat.cn/?p=30051 •研究生物体产生的全部蛋白质. • Foci:鉴定.结构测定.生物标志物.通路.表达(点击文末"阅读原文"获取完整代码 ...

  4. android陀螺仪轨迹,陀螺仪轨迹法长距离管道测量精度实测分析

    陀螺仪轨迹法长距离管道测量精度实测分析 陀螺仪轨迹法用于非开挖管道的精准坐标与位置测量已被电力与燃气等行业逐步了解与接受,近两年不断被引入到城市地下管线探测及电力与燃气管道验收标准中.由于管道埋于地下 ...

  5. 孙子兵法的计是最早的SWOT分析,《孙子兵法》首先不是战法,而是不战之法。首先不是战胜之法,而是不败之法...

    孙子兵法的计是最早的SWOT分析,<孙子兵法>首先不是战法,而是不战之法.首先不是战胜之法,而是不败之法 在打仗之前,你要详细地去算. 计算的目的是什么呢? 孙子说,是为了知胜,就是为了知 ...

  6. Nature综述:2万字带你系统入门鸟枪法宏基因组实验和分析

    NBT:鸟枪法宏基因组-从取样到数据分析 Shotgun metagenomics, from sampling to analysis Nature Biotechnology [IF:31.864 ...

  7. Python数据分析高薪实战第十二天 网络服务用户流失预测分析和国产电视剧评分预测分析

    29 综合实战:网络服务用户流失预测与分析 绝大多数互联网公司都面临一个非常重要的问题:用户流失问题.随着互联网和移动互联网的充分发展,发展新用户(也就是一般所说的拉新)的成本越来越高,往往要几块或者 ...

  8. python+appium爬取微信运动数据,并分析好友的日常步数情况

    python+appium爬取微信运动数据,并分析好友的日常步数情况 声明:仅供技术交流,请勿用于非法用途,如有其它非法用途造成损失,和本博客无关 目录 python+appium爬取微信运动数据,并 ...

  9. python如何做敏感度分析_Python中的模型敏感度分析(使用Salib)

    敏感度分析的基础概念 文本主要参考了维基百科(对其中的关键部分进行了摘选了翻译):https://en.wikipedia.org/wiki/Sensitivity_analysis​en.wikip ...

最新文章

  1. 使用Java HttpURLConnection抓取网页内容(一)限制返回的网页大小
  2. Git commit message和工作流规范
  3. Liunx 查看硬件信息
  4. java链表需要自己编写么_基于java的链表基础操作
  5. CVPR 2020 中的群组活动识别
  6. 计算机网络 socket阻塞非阻塞
  7. 1001. 害死人不偿命的(3n+1)猜想 (15)-PAT乙级真题
  8. 基于Ajax的应用程序架构汇总(一) (转自CSDN)
  9. ASP.NET 网站管理工具“安全”选项卡为什么打不开?
  10. 手机号、身份证格式校验
  11. 图片裁切批处理_Imgbot 在线图片批量处理工具 支持缩放、压缩、裁切、水印等...
  12. 龙芯2F入手,点滴记录!
  13. anaconda 和Tensorflow 2 安装
  14. 基于觅食生境选择的改进粒子群算法-附代码
  15. 佐治亚州立大学计算机科学,佐治亚州立大学计算机科学研究生语言及申请要求-费用-课程设置...
  16. 每2天一次付费做自费核酸检测用这3个APP应用让你更方便?
  17. 【模糊综合评价的运用】——《电子舌技术在食用盐模糊感官评价中的应用》论文笔记(内附MATLAB程序)
  18. 物联网开发笔记(54)- 使用Micropython开发ESP32开发板之控制MG90S舵机
  19. 2020焊工(技师)考试题及焊工(技师)复审模拟考试
  20. 研发效率破局之道-学习思考

热门文章

  1. angular4 - 思维导图(xmind)
  2. 循环码生成原理与FPGA实现
  3. 高通增强现实SDK开发实例,COCOACHINA首发。qualcomm ar sdk
  4. 天宇电梯卡数据分析延期教程 电梯卡延期校验计算工具
  5. proxifier注册码
  6. Chapter-5_统计推断_贝叶斯学派
  7. 微信小程序AES解密失败
  8. 音频卡是计算机硬件吗,绝对干货:关于声卡你需要知道的几点知识
  9. ebs workflow builder下载路径
  10. 大公司的开源项目~~~阿里,百度,腾讯,360,新浪,网易,小米等