层次分析法详细讲解+Python代码实现

3f6a7ab0347a4af1a75e6ebadee63fc1.gif

🤵‍♂️ 个人主页:@艾派森的个人主页

✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+


目录

问题的提出

层次分析法

基本概念

模型原理

基本步骤

①建立递阶层次结构模型

②构造出各层次中的所有判断矩阵

③一致性检验

④求权重

求评分

Python代码实现


584c44d833cb458f8d20b8cd3bb109ca.png

问题的提出

日常生活中有很多的决策问题。决策是指在面临多种方案时需要依据一定的标准选择某一种方案。

  • 买衣服,一般要依据质量、颜色、价格、款式等方面的因素选择
  • 旅游,是去风光秀丽的苏州,还是去迷人的北戴河,或者是去山水甲天下的桂林,那一般会依据景色、费用、食宿条件、旅途等因素来判断去哪个地方

研究问题:XX微博要选出一个明星作为微博之星,现在有三个候选明星A、B、C,该选择哪位明星呢?

考虑一个明星的成就可以看其粉丝数、颜值、作品数量、作品质量(考虑用作品某瓣平均评分代替)
A、B、C的相关数据如下:

9cdcc3e204144edd91b0b8ae1e24b2d1.png

思考:XX微博要选出一个明星作为微博之星,现在有三个候选明星A、B、C,该选择哪位明星呢?
怎么能让指标在同一数量级,且保证在同一指标下其差距不变?

归一化处理:指标的数组[a b c]归一化处理得到[a/(a+b+c),b/(a+b+c),c/(a+b+c)]

9faf8920e06a4ceb83269830e3c0d7c9.png

明星A当选吗?实际上每个指标的重要性是不同的。

来给每一个指标加上权重,微博公司考虑宣传效果,认为粉丝数最重要,作品数量最不重要。比如给人为的给粉丝数设定0.4的权重....

1e52d46f3b004201a9ee06a9390d0c42.png

这个方法大家肯定不陌生,比如在大学中的课程成绩,一般卷面成绩占比70%,平时成绩占比30%等,最后得到的成绩就是综合卷面成绩和平时成绩加权后的总分。

思考:这里我是随机设置的权重,如何科学地设定权重?

层次分析法

面临各种各样的方案,要进行比较、判断、评价、直至最后的决策。这个过程中都是一些主观的因素,这些因素可能由于个人情况的不同,有相应不同的比重,所以这样主观因素给数学方法的解决带来了很多的不便

基本概念

层次分析法(Analytic HierarchyProcess,简称AHP)是对一些较为复杂、较为模糊的问题作出决策的简易方法,它特别适用于那些难于完全定量分析的问题它是美国运筹学家 T.L. Saaty 教授于上世纪 70年代初期提出的一种简便、灵活而又实用的多准则决策方法。

模型原理

        应用 AHP 分析决策问题时,首先要把问题条理化、层次化,构造出一个有层次的结构模型。在这个模型下,复杂问题被分解为元素的组成部分。这些元素又按其属性及关系形成若干层次。上一层次的元素作为准则对下一层次有关元素起支配作用。这些层次可以分为三类:·

  • 最高层:这一层次中只有一个元素,一般它是分析问题的预定目标或理想结果,因此也称为目标层。
  • 中间层:这一层次中包含了为实现目标所涉及的中间环节,它可以由若千个层次组成,包括所需考虑的准则、子准则,因此也称为准则层·
  • 最底层:这一层次包括了为实现目标可供选择的各种措施、决策方案等,因此也称为措施层或方案层。

8c748f5dc2024aa5adee5fc85e69aa3b.png

对于我们刚刚提出的问题来说,目标层就是选出微博之星;中间层就是判断方案好坏的指标,对应的就是粉丝数、作品质量、作品数量等;最底层就是对应的A、B、C三位明星。

基本步骤

运用层次分析法建模,大体上可按下面四个步骤进行:

  1. 建立递阶层次结构模型
  2. 构造出各层次中的所有判断矩阵
  3. 一致性检验
  4. 求权重后进行评价

我们还是以选出微博之星的问题为例

①建立递阶层次结构模型

其递阶层次结构模型如下:

bf2b96a064e947149ae54a0e5c508ddc.png

②构造出各层次中的所有判断矩阵

  • 对指标的重要性进行两两比较,构造判断矩阵,从而科学求出权重
  • 矩阵中元素eq?a_%7Bij%7D的意义是,第i个指标相对第j个指标的重要程度

构造判断矩阵

37d57a30cabf40c68026ed25faa61101.png

粉丝数跟作品数量比显然明显重要,那么eq?a_%7B14%7D%3D5,反过来,作品数量相比粉丝数的重要性那就是1/5。

以此对变量进行两两比较,得到完整的判断矩阵,如下表:

97d67b3c4e094e5aac1eb509ca1fae27.png

因两两比较的过程中忽略了其他因素,导致最后的结果可能出现矛盾。

如上表可以看出eq?a_%7B23%7D=1/2代表在重要性上,颜值不如作品质量; eq?a_%7B24%7D =2代表着颜值比作品数量重要,因此可以看出作品质量比作品数量重要,但eq?a_%7B34%7D=1/2意味着作品质量不如作品数量重要,与上一条矛盾!所以需要一致性检验!

③一致性检验

77d8943312374646b9fb1d9180675efa.png

一致矩阵

若矩阵中每个元素eq?a_%7Bij%7D>0且满足eq?a_%7Bij%7D%5Ctimes%20a_%7Bji%7D%3D%201,则我们称该矩阵为正互反矩阵。在层次分析法中,我们构造的判断矩阵均是正互反矩阵。若正互反矩阵满足eq?a_%7Bik%7D%5Ctimes%20a_%7Bkj%7D%5Cdoteq%20a_%7Bij%7D,则我们称其为一致矩阵。比如下面这个矩阵就是一致矩阵。

f86d7e1ceb984f78b9755f9d21b0b69a.png

注意:在使用判断矩阵求权重之前,必须对其进行一致性检验,以免产生矛盾。

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

5e2305f4037b452ba86f591e8a7b88ea.png

一致性检验步骤:

1.计算一致性指标CI

eq?CI%3D%20%5Cfrac%7B%5Clambda%20_%7Bmax%7D-n%7D%7Bn-1%7D

2.查找对应的平均随机一致性指标RI

6de88c558bb74405a1bab41d10c43538.png

注:RI我们只需要会查表即可,不用管怎么来的。在实际运用中,n很少超过10,如果指标的个数大于10,则可考虑建立二级指标体系,或者使用模糊综合评价模型。

3.计算一致性比例CR

6346e12cb6d345eaa087e20747cadf8e.png

现在回到微博之星那个问题

97d67b3c4e094e5aac1eb509ca1fae27.png

当前判断矩阵的eq?%5Clambda%20_%7Bmax%7D=4.68,n=4,求得CI=0.227,查表RI=0.89,得CR=0.255,CR >0.1,需修改判断矩阵。

修改后判断矩阵如下:

75341aeb91e84ce48be44e8c2e54c292.png

当前判断矩阵的eq?%5Clambda%20_%7Bmax%7D=4.1128,n =4,求得CI=0.227,查表RI=0.89,得CR=0.0418,CR<0.1,通过一致性检验。

④求权重

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

  • 第一步:将判断矩阵按照列归一化(每一个元素除以其所在列的和)
  • 第二步:将归一化的各列相加(按行求和)
  • 第三步:将相加后得到的向量中每个元素除以n即可得到权重向量

816f8413b38e403ea47fbd3f3167d2da.png

用算术平均法求出微博之星的指标权重如下:

680480c8046c422e9aeaff0b71afc6bc.png

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

  • 第一步:将判断矩阵的元素按照行相乘得到一个新的列向量
  • 第二步:将新的向量的每个分量开n次方
  • 第三步:对该列向量进行归一化即可得到权重向量

644958f53c3941209642c79ce5d27ec4.png

用几何平均法求出微博之星的指标权重如下:

9279ddf4c8ac47b882d8cb485d162fd3.png

方法三:特征值法求权重

de7424987a7c48c7bc2df53c70da1abe.png

假如我们的判断矩阵一致性可以接受,那么我们可以仿照一致矩阵权重的求法。

  • 第一步:求出矩阵A的最大特征值以及其对应的特征向量
  • 第二步:对求出的特征向量进行归一化即可得到我们的权重

1e70abbc85464ae8b29351fcf403a7f9.png

最大特征值为4.1128        一致性比例CR=0.1128/3=0.04

其对应的特征向量:[0.8487    0.3076    0.3962    0.1676]

对其进行归一化得到权重:[0.493    0.179    0.230    0.097]

求评分

828b2531d32a4c8c9d81362bd8d42407.png

三种方法求得的权重基本上都差不多,那这里我们就用特征值法来求。

如果选择特征值法,综合评分=0.493*粉丝数+0.179*颜值+0.230*作品质量+0.097*作品数量

68fe42d41e6f47b9b55c4c227ee1f713.png

从最终评分结果来看,还是明星A获胜,应当选微博之星!

Python代码实现

首先是一致性检验,我们以前面的案例中的判断矩阵为例进行演示,首先使用原先的判断矩阵

import numpy as np
# 定义矩阵A,np.array 是 umpy 库中的一个函数,用于创建数组。它将输入的对象(如列表、元组、其他数组等)转换为 Mumpy 数组。
A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,1/2],[1/5,1/2,2,1]]) # 原判断矩阵
n = A.shape[0] # 获取A的行,0变为1则是获取A的列,shape是获取形状信息

# 求出最大特征值以及对应的特征向量,np.linalg.eig是NumPy 库中的一个函数,用于计算方阵的特征值和特征向量。
eig_val,eig_vec = np.linalg.eig(A) # eig_val是特征值,eig_vec是特征向量
Maxeig = max(eig_val) # 求特征值的最大值

CI = (Maxeig-n)/(n-1)
RI = [0,0.0001,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] 
# 注意哦,这里的RI最多支持n=15
# 这里n=2时,一定是一致矩阵,所以CI =0,我们为了避免分母为0,将这里的第二个元素改为了很接近0的正数

CR = CI/RI[n-1]
print('一致性指标CI =',CI)
print('一致性比例CR =',CR)
if CR< 0.10:
    print('因为CR<0.10,所以该判断矩阵A的一致性可以接受!')
else:
    print('注意:CR>= 0.10,因此该判断矩阵A需要进行修改!')

代码运行结果如下:

a2b6c343814d435ba2f6abefefb45a1e.png

将代码中的判断进行修改

A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,2],[1/5,1/2,1/2,1]]) # 修改后的判断矩阵

重新运行结果如下:

564348ce31774b24860a79126c309517.png

接着求权重

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

import numpy as np
# 定义判断矩阵A
A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,2],[1/5,1/2,1/2,1]])
# 计算每列的和
# np.sum 函数可以计算一维数组中所有元素的总和。
# 还可以通过指定 axis 參数来计算多维数组的某个维度上的元素总和。例如,在二维数组中,axis=0 表示按列计算总和,axis=1 表示按行计算总和。
ASum = np.sum(A, axis=0)
# 获取A的行和列
n = A.shape[0]
# 归一化,二维数组除以一维数组,会自动将一维数组扩展为与二维数组相同的形状,然后进行逐元素的除法运算。
stand_A = A/ASum
# 各列相加到同一行
ASumr = np.sum(stand_A, axis=1)
#计算权重向量
weights = ASumr/n
print('算术平均法求的权重结果为:',weights)

代码运行结果:

0d816b251a0f4f869b9828069b3c4484.png

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

import numpy as np
# 定义判断矩阵A
A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,2],[1/5,1/2,1/2,1]])
# 获取A的行和列
n = A.shape[0]
# 将A中每一行开素相乘得到一列向量
# np.prod 函数可以计算一维数组中所有元素的乘积。
# 还可以通过指定 axis 參数来计算多维数组的某个维度上的元素柔积。例如,在二维数组中,axis=0 表示按列计算乘积,axis=1 表示按行计算乘积。
prod_A = np.prod(A, axis=1)
# 将新的向量的每个分量开n次方等价求1/n次方
# np.power是NumPy库中的一个函数,用于对数组中的元素进行运。
# 例如,可以使用np.power(a,b)对数组a中的每个元素都按照b指数进行运算。
prod_n_A=np.power(prod_A, 1/n)
# 归一化处理
re_prod_A= prod_n_A/ np.sum(prod_n_A)
# 打印权重结果
print('几何平均法求的权重结果为:',re_prod_A)

代码运行结果:

9089f5acb90a42eaa69a9ae598d74533.png

方法三:特征值法求权重

import numpy as np
# 定义判断矩阵A
A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,2],[1/5,1/2,1/2,1]])
# 获取A的行
n = A.shape[0]
# 求出特征值和特征向量
eig_values,eig_vectors = np.linalg.eig(A)
# 找出最大特征值的索引,np.argmax是umPy库中的一个函数,用于返回数组中最大值的索引
max_index = np.argmax(eig_values)
# 找出对应的特征向量
max_vector = eig_vectors[:, max_index]
# 对特征向量进行归一化处理,得到权重
weights = max_vector /np.sum(max_vector)
# 输出权重
print('特征值法求的权重结果为:',weights)

a30121054dfa46d9b7386ef3f8c0fbb4.png

最后,我们将前面的一致性检验和求权重代码进行汇总,编写一个层次分析法的类,用来求权重

import numpy as np
class AHP:
    """
    相关信息的传入和准备
    """

    def __init__(self, array):
        ## 记录矩阵相关信息
        self.array = array
        ## 记录矩阵大小
        self.n = array.shape[0]
        # 初始化RI值,用于一致性检验
        self.RI_list = [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]
        # 矩阵的特征值和特征向量
        self.eig_val, self.eig_vector = np.linalg.eig(self.array)
        # 矩阵的最大特征值
        self.max_eig_val = np.max(self.eig_val)
        # 矩阵最大特征值对应的特征向量
        self.max_eig_vector = self.eig_vector[:, np.argmax(self.eig_val)].real
        # 矩阵的一致性指标CI
        self.CI_val = (self.max_eig_val - self.n) / (self.n - 1)
        # 矩阵的一致性比例CR
        self.CR_val = self.CI_val / (self.RI_list[self.n - 1])

    """
    一致性判断
    """

    def test_consist(self):
        # 打印矩阵的一致性指标CI和一致性比例CR
        print("判断矩阵的CI值为:" + str(self.CI_val))
        print("判断矩阵的CR值为:" + str(self.CR_val))
        # 进行一致性检验判断
        if self.n == 2:  # 当只有两个子因素的情况
            print("仅包含两个子因素,不存在一致性问题")
        else:
            if self.CR_val < 0.1:  # CR值小于0.1,可以通过一致性检验
                print("判断矩阵的CR值为" + str(self.CR_val) + ",通过一致性检验")
                return True
            else:  # CR值大于0.1, 一致性检验不通过
                print("判断矩阵的CR值为" + str(self.CR_val) + "未通过一致性检验")
                return False

    """
    算术平均法求权重
    """

    def cal_weight_by_arithmetic_method(self):
        # 求矩阵的每列的和
        col_sum = np.sum(self.array, axis=0)
        # 将判断矩阵按照列归一化
        array_normed = self.array / col_sum
        # 计算权重向量
        array_weight = np.sum(array_normed, axis=1) / self.n
        # 打印权重向量
        print("算术平均法计算得到的权重向量为:\n", array_weight)
        # 返回权重向量的值
        return array_weight

    """
    几何平均法求权重
    """

    def cal_weight_by_geometric_method(self):
        # 求矩阵的每列的积
        col_product = np.product(self.array, axis=0)
        # 将得到的积向量的每个分量进行开n次方
        array_power = np.power(col_product, 1 / self.n)
        # 将列向量归一化
        array_weight = array_power / np.sum(array_power)
        # 打印权重向量
        print("几何平均法计算得到的权重向量为:\n", array_weight)
        # 返回权重向量的值
        return array_weight

    """
    特征值法求权重
    """

    def cal_weight_by_eigenvalue_method(self):
        # 将矩阵最大特征值对应的特征向量进行归一化处理就得到了权重
        array_weight = self.max_eig_vector / np.sum(self.max_eig_vector)
        # 打印权重向量
        print("特征值法计算得到的权重向量为:\n", array_weight)
        # 返回权重向量的值
        return array_weight


if __name__ == "__main__":
    # 给出判断矩阵
    A = np.array([[1,2,3,5],[1/2,1,1/2,2],[1/3,2,1,1/2],[1/5,1/2,2,1]])
    # 初始化
    ahp = AHP(A)
    # 检测是否通过一致性检验
    if ahp.test_consist():
        # 算术平均法求权重
        weight1 = ahp.cal_weight_by_arithmetic_method()
        # 几何平均法求权重
        weight2 = ahp.cal_weight_by_geometric_method()
        # 特征值法求权重
        weight3 = ahp.cal_weight_by_eigenvalue_method()

运行结果如下:

2785d0956c13404b8165a48eb948652c.png

如果给出正确的判断矩阵A

A = np.array([[1, 1 / 3, 1 / 8], [3, 1, 1 / 3], [8, 3, 1]])

运行结果如下:

6eb3de1061bb42d9aba55cfed5284687.png

在上面的代码中,我们只需要更改判断矩阵A变量即可使用!

资料获取,更多粉丝福利,关注下方公众号获取

a74f7d5d03234f7c8a635562034442a0.gif#pic_center

 

层次分析法(Analytic Hierarchy Process,AHP)是一种用于多准则决策的方法,其目标是通过对准则的相对重要性进行定量评估,并对各个备选方案进行排序。下面是一个使用Python实现AHP的代码示例: ```python import numpy as np from numpy import linalg class AHP: def __init__(self, matrix): self.matrix = matrix def cal_weight_by_arithmetic_method(self): n = len(self.matrix) b = np.sum(self.matrix, axis=0) normal_a = self.matrix / b average_weight = np.mean(normal_a, axis=1) return average_weight def cal_weight_by_geometric_method(self): n = len(self.matrix) b = np.prod(self.matrix, axis=1) c = np.power(b, 1/n) average_weight = c / np.sum(c) return average_weight def cal_weight_by_eigenvalue_method(self): n = len(self.matrix) w, v = linalg.eig(self.matrix) eigenvalue = np.max(w) eigenvector = v[:, np.argmax(w)] average_weight = eigenvector / np.sum(eigenvector) return average_weight # 示例用法 if __name__ == "__main__": b = np.array([[1, 1/3, 1/8], [3, 1, 1/3], [8, 3, 1]]) ahp = AHP(b) weight1 = ahp.cal_weight_by_arithmetic_method() weight2 = ahp.cal_weight_by_geometric_method() weight3 = ahp.cal_weight_by_eigenvalue_method() ``` 这段代码实现了AHP的算术平均法、几何平均法和特征值法,可以根据输入的判断矩阵计算出相应的权重。其中,`cal_weight_by_arithmetic_method()`函数实现了算术平均法,`cal_weight_by_geometric_method()`函数实现了几何平均法,`cal_weight_by_eigenvalue_method()`函数实现了特征值法。每个方法返回的是一个代表权重的一维数组。 请注意,代码中使用了NumPy库进行矩阵运算和线性代数计算。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [数学建模——层次分析法Python代码](https://blog.csdn.net/qq_45934521/article/details/118972017)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* *3* [AHP层次分析法python代码讲解(处理论文、建模)](https://blog.csdn.net/knighthood2001/article/details/127519604)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 72
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

艾派森

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值