AHP(层次分析法)的全面讲解及python实现

时间:2024-03-22 08:21:17

一、层次分析法的使用流程:

1. 建立层次结构模型

首先绘出层次结构图,正常三层是比较常见的:决策的目标、考虑的决策准则因素和决策对象。按它们之间的相互关系分为最高层、中间层和最低层(如下图是四层结构的)

AHP(层次分析法)的全面讲解及python实现

2. 分层构造判断矩阵。多层次的评价指标体系结构一般比较复杂,各种评价指标的权重难以确定,通过两两比较评价因子的重要性来确定权重要比一次性确定所有因子的权重容易把握。该方法叫一致矩阵法,即:不把所有因素放在一起比较,而是两两相互比较。对比时采用相对尺度,以尽可能减少性质不同因素相互比较的困难,以提高准确度。

AHP(层次分析法)的全面讲解及python实现

由专家对同一层次内N个指标的相对重要性(两两因素之间)进行打分。相对重要性的比例标度取1-9之间。同时,对各同级指标的重要性评价时,存在三种标度范畴(如下图),根据研究需要自行选择。

AHP(层次分析法)的全面讲解及python实现

对于n个元素而言,可得两两比较判断矩阵A(正交矩阵):AHP(层次分析法)的全面讲解及python实现

满足:AHP(层次分析法)的全面讲解及python实现

3. 计算权重。将矩阵A的各行向量进行几何平均(方根法),然后进行归一化,即得到各评价指标权重和特征向量W。即权重向量AHP(层次分析法)的全面讲解及python实现可直接由下式得出:AHP(层次分析法)的全面讲解及python实现,其中AHP(层次分析法)的全面讲解及python实现

 

4. 一致性检验。若A是一致矩阵,那么A的最大特征值AHP(层次分析法)的全面讲解及python实现所对应的特征向量即准确地对应于权重向量W.

AHP(层次分析法)的全面讲解及python实现

对判断矩阵,通用的计算权向量方法有和法、根法、特征根法和最小平方法等方法,以和法为例:

1、矩阵按列归一化:AHP(层次分析法)的全面讲解及python实现,n为参加比较的元素数

2、正规化后的元素按行相加: AHP(层次分析法)的全面讲解及python实现

3、将得到的行和向量进行归一化即得权重:AHP(层次分析法)的全面讲解及python实现

实际应用中,判断矩阵A一般不可能是一致矩阵,因此要进行一致性检验,检查该方法得到的权重向量是否有效。

计算一致性指标CI:AHP(层次分析法)的全面讲解及python实现,n为判断矩阵的阶数

AHP(层次分析法)的全面讲解及python实现

根据n值平均随机一致性指标RI,RI值可查表:

n

1

2

3

4

5

6

7

8

9

10

RI

0

0

0.58

0.9

1.12

1.24

1.32

1.41

1.45

1.49

计算一致性比例CR:AHP(层次分析法)的全面讲解及python实现,

当CR小于0.1时,一般认为判断矩阵的一致性是可以接受的。所谓一致性是指判断思维的逻辑一致性。如当甲比丙是强烈重要,而乙比丙是稍微重要时,显然甲一定比乙重要。这就是判断思维的逻辑一致性,否则判断就会有矛盾。

5. 层次排序。可分为层次单排序和层次总排序。所谓层次单排序是指,对于上一层某因素而言,本层次各因素的重要性的排序。层次总排序,确定某层所有因素对于总目标相对重要性的排序权值过程,称为层次总排序。这一过程是从最高层到最底层依次进行的。对于最高层而言,其层次单排序的结果也就是总排序的结果

 

 

二、层次分析法实例分析:

1. 建立层次结构模型

假设有m个候选方案,有n个准则。例如一位顾客决定要买一套新住宅,经过初步调查研究确定了三套候选的房子A、B、C,即AHP(层次分析法)的全面讲解及python实现,问题是如何在这三套房子里选自一套较为满意的房子呢? 下面给出有关的数据和资料:

将影响购买新房的因素归纳为4个标准:

房子的地理位置及交通;

房子的居住环境;

  房子结构、布局与设施;

  房子的每平方米建筑面积地单价。

即有m=3个候选方案,n=4个评价指标,分别是地理位置及交通、居住环境、结构布局与设施、每平方米建筑面积地单价)

模型如下:

AHP(层次分析法)的全面讲解及python实现

2. 构造判断矩阵

对同一层次内4个指标的相对重要性(两两因素之间)进行打分。经过专家的打分,每个标准的两两比较矩阵可给出,其中以地理位置以及交通情况对应的三个方案的判断矩阵为例,其值如下:

AHP(层次分析法)的全面讲解及python实现

3. 计算权重

我们利用和法来将矩阵按列归一化得到:

AHP(层次分析法)的全面讲解及python实现

再将正规化后的元素按行相加,将得到的行和向量进行归一化即得特征向量:

AHP(层次分析法)的全面讲解及python实现

4. 一致性检验

判断矩阵乘以特征向量得到赋权和向量

AHP(层次分析法)的全面讲解及python实现

赋权和向量除以对应权重得到:

1.803 / 0.593 =3.040

1.034 / 0.341 =3.032

0.197 / 0.066 =2.985

计算出第二步结果中的平均值,记为AHP(层次分析法)的全面讲解及python实现AHP(层次分析法)的全面讲解及python实现

计算一致性指标CI:AHP(层次分析法)的全面讲解及python实现

计算一致性率CR:AHP(层次分析法)的全面讲解及python实现

用同样的方法我们可以得到其他三个标准对应三个购房方案的特征向量,以及购房决策四个标准的特征向量,这里就不重复写求解过程,假设最终得到所有特征向量如下:

AHP(层次分析法)的全面讲解及python实现

5. 综合得分

方案 A:0.398*0.593+0.218*0.123+0.085*0.087+0.299*0.265=0.349

方案 B(最优):0.398*0.341+0.218*0.320+0.085*0.274+0.299*0.655=0.425

方案 C:0.398*0.066+0.218*0.557+0.085*0.639+0.299*0.080=0.226

 

 

三、python完整代码

注释:本代码数据与上述实例数值不完全匹配,但方法雷同

import numpy as np
import pandas as pd
import warnings


class AHP:
   
def __init__(self, criteria, samples):
       
self.RI = (0, 0, 0.58, 0.9, 1.12, 1.24, 1.32, 1.41, 1.45, 1.49)
       
self.criteria = criteria
       
self.samples = samples
       
self.num_criteria = criteria.shape[0]
       
self.num_project = samples[0].shape[0]

   
def calculate_weights(self, input_matrix):
        input_matrix = np.array(input_matrix)
        n, n1 = input_matrix.shape
       
assert n==n1, "the matrix is not orthogonal"
       
for i in range(n):
           
for j in range(n):
               
if np.abs(input_matrix[i,j]*input_matrix[j,i]-1) > 1e-7:
                    
raise ValueError("the matrix is not symmetric")
        eigen_values, eigen_vectors = np.linalg.eig(input_matrix)
        max_eigen = np.max(eigen_values)
        max_index = np.argmax(eigen_values)
        eigen = eigen_vectors[:, max_index]
        eigen = eigen/eigen.sum()
       
if n > 9:
            CR =
None
           
warnings.warn("can not judge the uniformity")
       
else:
            CI = (max_eigen - n)/(n-
1)
            CR = CI /
self.RI[n-1]
       
return max_eigen, CR, eigen

   
def calculate_mean_weights(self,input_matrix):
        input_matrix = np.array(input_matrix)
        n, n1 = input_matrix.shape
       
assert n == n1, "the matrix is not orthogonal"
       
A_mean = []
       
for i in range(n):
            mean_value = input_matrix[:, i]/np.sum(input_matrix[:, i])
            A_mean.append(mean_value)
        eigen = []
        A_mean = np.array(A_mean)
       
for i in range(n):
            eigen.append(np.sum(A_mean[:, i])/n)
        eigen = np.array(eigen)
        matrix_sum = np.dot(input_matrix, eigen)
        max_eigen = np.mean(matrix_sum/eigen)
       
if n > 9:
            CR =
None
           
warnings.warn("can not judge the uniformity")
       
else:
            CI = (max_eigen - n) / (n -
1)
            CR = CI /
self.RI[n - 1]
       
return max_eigen, CR, eigen

   
def run(self, method="calculate_weights"):
        weight_func =
eval(f"self.{method}")
        max_eigen, CR, criteria_eigen = weight_func(
self.criteria)
       
print('准则层:最大特征值{:<5f},CR={:<5f},检验{}通过'.format(max_eigen, CR, '' if CR < 0.1 else '不'))
       
print('准则层权重={}\n'.format(criteria_eigen))

        max_eigen_list, CR_list, eigen_list = [], [], []
       
for sample in self.samples:
            max_eigen, CR, eigen = weight_func(sample)
            max_eigen_list.append(max_eigen)
            CR_list.append(CR)
            eigen_list.append(eigen)

        pd_print = pd.DataFrame(eigen_list,
index=['准则' + str(i+1) for i in range(self.num_criteria)],
                                
columns=['方案' + str(i+1) for i in range(self.num_project)],
                                )
        pd_print.loc[:,
'最大特征值'] = max_eigen_list
        pd_print.loc[:,
'CR'] = CR_list
        pd_print.loc[:,
'一致性检验'] = pd_print.loc[:, 'CR'] < 0.1
       
print('方案层')
       
print(pd_print)

       
# 目标层
       
obj = np.dot(criteria_eigen.reshape(1, -1), np.array(eigen_list))
       
print('\n目标层', obj)
       
print('最优选择是方案{}'.format(np.argmax(obj)+1))
       
return obj


if __name__ == '__main__':
   
# 准则重要性矩阵
   
criteria = np.array([[1, 2, 7, 5],
                         [
1 / 2, 1, 4, 3],
                         [
1 / 7, 1 / 4, 1, 1 / 2],
                         [
1 / 5, 1 / 3, 2, 1]])

   
# 对每个准则,方案优劣排序
   
sample1 = np.array([[1, 2, 8], [1/2, 1, 6], [1/8, 1/6, 1]])
    sample2 = np.array([[
1, 2, 5], [1 / 2, 1, 2], [1 / 5, 1 / 2, 1]])
    sample3 = np.array([[
1, 1, 3], [1, 1, 3], [1 / 3, 1 / 3, 1]])
    sample4 = np.array([[
1, 3, 4], [1 / 3, 1, 1], [1 / 4, 1, 1]])

    samples = [sample1, sample2, sample3, sample4]
    a = AHP(criteria, samples).run(
"calculate_mean_weights")

输出结果:AHP(层次分析法)的全面讲解及python实现

四、层次分析法优点:

优点:

1. 系统性的分析方法

层次分析法把研究对象作为一个系统,按照分解、比较判断、综合的思维方式进行决策,成为继机理分析、统计分析之后发展起来的系统分析的重要工具。系统的思想在于不割断各个因素对结果的影响,而层次分析法中每一层的权重设置最后都会直接或间接影响到结果,而且在每个层次中的每个因素对结果的影响程度都是量化的,非常清晰明确。这种方法尤其可用于对无结构特性的系统评价以及多目标、多准则、多时期等的系统评价。

2. 简洁实用的决策方法

这种方法既不单纯追求高深数学,又不片面地注重行为、逻辑、推理,而是把定性方法与定量方法有机地结合起来,使复杂的系统分解,能将人们的思维过程数学化、系统化,便于人们接受,且能把多目标、多准则又难以全部量化处理的决策问题化为多层次单目标问题,通过两两比较确定同一层次元素相对上一层次元素的数量关系后,最后进行简单的数学运算。计算简便,并且所得结果简单明确,容易为决策者了解和掌握。

3. 所需定量数据信息较少

层次分析法主要是从评价者对评价问题的本质、要素的理解出发,比一般的定量方法更讲求定性的分析和判断。由于层次分析法是一种模拟人们决策过程的思维方式的一种方法,层次分析法把判断各要素的相对重要性的步骤留给了大脑,只保留人脑对要素的印象,化为简单的权重进行计算。这种思想能处理许多用传统的最优化技术无法着手的实际问题。

 

缺点:

1. 不能为决策提供新方

层次分析法的作用是从备选方案中选择较优者。在应用层次分析法的时候,可能就会有这样一个情况,就是我们自身的创造能力不够,造成了我们尽管在我们想出来的众多方案里选了一个最好的出来,但其效果仍然不够企业所做出来的效果好。而对于大部分决策者来说,如果一种分析工具能替我分析出在我已知的方案里的最优者,然后指出已知方案的不足,又或者甚至再提出改进方案的话,这种分析工具才是比较完美的。但显然,层次分析法还没能做到这点。

2. 定量数据较少,定性成分多,不易令人信服

在如今对科学的方法的评价中,一般都认为一门科学需要比较严格的数学论证和完善的定量方法。但现实世界的问题和人脑考虑问题的过程很多时候并不是能简单地用数字来说明一切的。层次分析法是一种带有模拟人脑的决策方式的方法,因此必然带有较多的定性色彩。

3. 指标过多时,数据统计量大,且权重难以确定

当我们希望能解决较普遍的问题时,指标的选取数量很可能也就随之增加。指标的增加就意味着我们要构造层次更深、数量更多、规模更庞大的判断矩阵。那么我们就需要对许多的指标进行两两比较的工作。由于一般情况下我们对层次分析法的两两比较是用1至9来说明其相对重要性,如果有越来越多的指标,我们对每两个指标之间的重要程度的判断可能就出现困难了,甚至会对层次单排序和总排序的一致性产生影响,使一致性检验不能通过。不能通过,就需要调整,在指标数量多的时候比较难调整过来。

4. 特征值和特征向量的精确求法比较复杂

在求判断矩阵的特征值和特征向量时,所用的方法和我们多元统计所用的方法是一样的。在二阶、三阶的时候,我们还比较容易处理,但随着指标的增加,阶数也随之增加,在计算上也变得越来越困难。不过幸运的是这个缺点比较好解决,我们有三种比较常用的近似计算方法。第一种就是和法,第二种是幂法,还有一种常用方法是根法(来自百度百科)。

 

 

文章参考连接:https://zhuanlan.zhihu.com/p/93109898