实际生活中,往往有一些很复杂的系统,我们没办法直观草率的确定权重,比如甲、乙、丙三人竞选总统,严谨的说,需要从三人的社交能力、管理能力、经济能力等方面来考虑,在每个方面,三位候选人的得分也不同,那么到底怎么来判断这三个人的综合得分呢?AHP可以帮助你。(请忽略现在的选举都是投票这个现实)
层次分析法是指将一个复杂的多目标决策问题作为一个系统,将目标分解为多个目标或准则,进而分解为多指标(或准则、约束)的若干层次,通过定性指标模糊量化方法算出层次单排序(权数)和总排序,以作为目标(多指标)、多方案优化决策的系统方法。
层次分析法是将决策问题按总目标、各层子目标、评价准则直至具体的备投方案的顺序分解为不同的层次结构,然后用求解判断矩阵特征向量的办法,求得每一层次的各元素对上一层次某元素的优先权重,最后再加权和的方法递阶归并各备择方案对总目标的最终权重,此最终权重最大者即为最优方案。
层次分析法比较适合于具有分层交错评价指标的目标系统,而且目标值又难于定量描述的决策问题。
下面是代码:
因为注释较多,根本无需一步一步的详解就能看懂,所以就一下子全放上来了。
#思路:
#1.首先输入每个指标下面对应的判断矩阵,
#该矩阵中的值是通过大数据(或者专家)得到的每两个指标之间的相对重要程度值,
#通过AHP计算这些判断矩阵是否通过一致性的检验,通过即合理,
#不通过就说明矩阵中的两指标间的相对重要程度有过分矛盾的地方,
import csv
import numpy as np
import tensorflow as tf
#定义一个叫AHP的类
class AHP:
def __init__(self,array):#array是每个指标下面对应的判断矩阵,即原始数据
self.row = len(array)#计算矩阵的行数
self.col = len(array[0])#计算矩阵的列数
def get_tezheng(self,array):#获取最大特征值和对应的特征向量
te_val ,te_vector = np.linalg.eig(array)#numpy.linalg.eig() 计算矩阵特征值与特征向量
list1=list(te_val)#te_val是一个一行三列的矩阵,此处将矩阵转化为列表
print("特征值为:",te_val)
print("特征向量为:",te_vector)
#得到最大特征值对应的特征向量
max_val = np.max(list1)#最大特征值
index = list1.index(max_val)#最大特征值在列表中的位置
max_vector = te_vector[:,index]#通过位置来确定最大特征值对应的特征向量
print("最大的特征值:"+str(max_val)+" 对应的特征向量为:"+str(max_vector))
return max_val,max_vector
def RImatrix(self,n):#建立RI矩阵,该矩阵是AHP中自带的,类似标杆一样,除n之外的值不能更改
d = {}
n1 = [1,2,3,4,5,6,7,8,9]
n2 = [0,0,0.58,0.90,1.12,1.24,1.32,1.41,1.45]
for i in range(n):#获取n阶矩阵对应的RI值
d[n1[n]] = n2[n]
print("该矩阵在一致性检测时采用的RI值为:",d[n1[n]])
return d[n1[n]]
def test_consitstence(self,max_val,RI): #测试一致性,AHP中最重要的一步,用于检验判断矩阵中的数据是否自相矛盾
CI = (max_val-self.row)/(self.row-1) #AHP中计算CI的标准公式
CR = CI/RI #AHP中计算CR的标准公式
if CR < 0.10 :
print("判断矩阵的CR值为 " +str(CR) + "通过一致性检验")
return True
else:
print("判断矩阵的CR值为 " +str(CR) + "判断矩阵未通过一致性检验,请重新输入判断矩阵")
return False
def normalize_vector(self,max_vector):#特征向量归一化
vector_after_normalization=[]#生成一个空白列表,用于存放归一化之后的特征向量的值
sum0 = np.sum(max_vector)#将特征向量的每一个元素相加取和
for i in range(len(max_vector)):
#将特征向量的每一个元素除以和,得到比值,保证向量的每一个元素都在0和1之间,直线归一化
#将归一化之后的元素依次插入空白列表的尾部
vector_after_normalization.append(max_vector[i]/sum0)
print("该级指标的权重矩阵为: "+str(vector_after_normalization))
return vector_after_normalization
def weightCalculator(self, normalMatrix):#计算最终指标对应的权重值
#layers weight calculations.
listlen = len(normalMatrix) -1 #设置listlen的初始值为normalMatrix最后一个元素的index
layerWeights = list()#空白权重列表
while listlen > -1:
sum = float()#sum的初始值为0.0,并且限制了sum的类型为浮点型
for i in normalMatrix:
sum+= i[listlen] #求normalMatrix各元素的和
sumAverage = round(sum / len(normalMatrix),3)#求normalMatrix各元素的平均值,并保留三位小数
layerWeights.append(sumAverage)#为什么平均值是权重??????
listlen-=1
return layerWeights
import csv
import numpy as np
import tensorflow as tf
def main():#这里需要确定指标的规模即多少个一级指标,多少个二级指标,这样才能确定要计算多少个对比矩阵
array1=[]
array2=[]
def define_structure():#构造AHP的层次结构
level_structure = []
level = int(input("请输入指标的级数:"))#输入比如说这是个三级指标体系
level0 = input("请输入每一级下指标的个数:")
level.append(level0)#将列表level0作为一个元素插入到列表level的末尾
level2 = []
for i in range(level):#每一级指标下有多少具体的指标个数
rate_num = input("请输入" +str(i)+ "层下指标的个数:")
#level2.append(rate_num)
for j in range(rate_num ):
two_level_for_one = int(input("请输入第" +str(i)+ " 个一级指标对应的下级指标的个数:"))
level_structure.append(two_level_for_one )
return level_structure
def creat_matrix(n):
n = define_structure()
for i in n:
length = input("请输入指标对比矩阵的阶数:")#对应指标下共有多少个相互对比的对象
length = int(length)#向下取整,若length=3.7,则int(length)=3
count=0
for i in range(length):#若length=3,则这部分实现的是,输入矩阵中3*3=9个元素的值
for j in range(length):
count += 1
x = input("请输入指标对比矩阵的第"+str(count)+ " 个元素:")
x = float(x)
array1.append(x)#此时的array1还不是一个矩阵,只是包含9个元素的列表
#eg:array1=[4,7,8,2,1,13,16,5,11]
for i in range(length*length):#将列表array1矩阵化
if (i+1)%length==0:#使用i+1是为了避免i=0的情况,因为0%3==0是true
array2.append(array1[i-length+1:i+1])#每3个元素形成一个列表插入到array2的末尾
print(array2)#eg:array2=[[4,7,8],[2,1,13],[16,5,11]]矩阵形式
array2=np.mat(array2)#NumPy函数库中的matrix与MATLAB中matrices等价,由于AHP是比较数学的东西,所以习惯的mat一下矩阵
a=AHP(array2)
max_val,max_vector = a.get_tezheng(array2)#获取最大特征值和对应的特征向量
RI= a.RImatrix(length)#获取length阶矩阵对应的RI值
flag = a.test_consitstence(max_val,RI)#测试一致性,返回TRUE或者flase
if flag:#如果flag=TRUE,则调用函数通过最大特征值对应的特征向量获取权重矩阵
weight = a.normalize_vector(max_vector)
main()
可以拷贝到本地慢慢消化,相信如此完备的注释会大大的有助于您的学习。
此代码为多年前的代码了,最近重新运行一遍,竟然报错了,不知哪里的问题,还望有经验的大神指正。