【数模修炼之旅】01 层次分析法 深度解析(教程+代码)

接下来 C君将会用至少30个小节来为大家深度解析数模领域常用的算法,大家可以关注这个专栏,持续学习哦,对于大家的能力提高会有极大的帮助。​

1 层次分析法介绍及应用

层次分析法是数模领域最常用的算法,应用于分配各指标权重。官方的话术是:

层次分析法,简称AHP,是指将与决策总是有关的元素分解成目标、准则、方案等层次,在此基础之上进行定性和定量分析的决策方法。该方法是美国运筹学家匹兹堡大学教授萨蒂于20世纪70年代初,在为美国国防部研究"根据各个工业部门对国家福利的贡献大小而进行电力分配"课题时,应用网络系统理论和多目标综合评价方法,提出的一种层次权重决策分析方法。

总体而言,这个是分配指标权重的最常用,也是最初级的做法。进阶的做法会在后面的章节介绍。

除此之外,它也可以用于量化方案的选择。

2 层次分析法的过程详解

2.1 分析过程

层次分析法的原理,是在分析一个现象或问题之前,首先将现象或问题根据它们的性质分解为有关因素,并根据它们之间的关系分类而形成一个多层次的结构模型。然后通过经验或专家,来判断和衡量低层因素对高层因素的相对重要性,并根据重要性的程度得出权重排序,进而可以量化分析比较。层次分 析法的核心是将影响因素层次化和数据化,它把一个抽象的现象或问题由难到 易地予以分解,易于对复杂问题进行直观地判断,并作出决策。层次分析法具有将复杂问题简单化且计算简单等优点,应用十分广泛,诸如在人员素质评估、 多方案比较、科技成果评比和工作成效评价等多领域多方面都有运用。

简单地说,层次分析法就是将一个决策事件分解为目标层(例如选择旅游地),准则层(影响决策的因素,例如景色、交通、费用等)以及方案层(指的是方案,例如去广州、桂林等地旅游)。

层次分析法应用过程中,大体步骤主要包括四个。第一步是层次结构模型的构建。第二步构造判断矩阵,第三步为层次单排序及其一致性检验,这步即为对指标定权,第四步为层次总排序及其一致性检验,这布如果没有决策层的话,通常可以省略。

PS:一致性检验的含义用于确定构建的判断矩阵是否存在逻辑问题,例如以A、B、C构建判断矩阵,若判定A相当于B为3(A比B稍微重要),A相当于C为1/3(C比A稍微重要),在判断B相当于C时,根据上述的逻辑,理应C比B重要,若我们在构建判断矩阵时,错误填写为B相当于C为3(B比C稍微重要),那么就犯了逻辑错误。

2.2 计算步骤

需要进行以下六步:

1. 构建层次结构模型

  • 目标层:这是决策的最终目标或目的。
  • 准则层:用于评估选择的各个准则或标准。
  • 备选方案层:具体的备选方案或决策选项。

2. 构造判断矩阵

  • 对于每个准则,使用1-9标度法对各个因素进行两两比较,构造出成对比较矩阵。判断矩阵中的元素a_ij表示相对于第j个元素,第i个元素的重要性。
  • 比例标度通常如下:
  • 1:同样重要
  • 3:略微重要
  • 5:明显重要
  • 7:强烈重要
  • 9:绝对重要
  • 2, 4, 6, 8:介于两者之间的中间值

3. 计算判断矩阵的特征向量和特征值

  • 对判断矩阵进行标准化处理。
  • 计算判断矩阵的最大特征值λ_max及对应的特征向量,并将特征向量归一化,这个归一化后的特征向量即为准则的权重向量。

4. 一致性检验

  • 计算一致性指标(CI):
  • 其中,n是判断矩阵的阶数。
  • 查表得到随机一致性指数(RI)。
  • 计算一致性比率(CR):
  • 如果CR < 0.1,则认为判断矩阵具有满意的一致性,否则需要重新调整判断矩阵。

5. 计算各备选方案的综合权重

  • 对于每个准则,按照该准则对各备选方案的影响进行两两比较,构建判断矩阵,计算各备选方案在该准则下的权重。
  • 最后,将各准则的权重与各备选方案在该准则下的权重相乘,求和得到每个备选方案的综合权重。

6. 排序与决策

  • 根据综合权重对备选方案进行排序,权重最高的方案为最优方案。

3 层次分析法代码(python+matlab)

python代码如下:

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__":
    # 给出判断矩阵
    b = np.array([[1, 1 / 3, 1 / 8], [3, 1, 1 / 3], [8, 3, 1]])

    # 算术平均法求权重
    weight1 = AHP(b).cal_weight_by_arithmetic_method()
    # 几何平均法求权重
    weight2 = AHP(b).cal_weight__by_geometric_method()
    # 特征值法求权重
    weight3 = AHP(b).cal_weight__by_eigenvalue_method()

matlab代码如下:

使用方法
(1)构造判断矩阵A
(2)将下文代码复制粘贴到Matlab中即可
例如:A=[1 3 5;0.33 1 3;0.2 0.33,1]

disp('请输入准则层判断矩阵A(n阶)');
A=input('A=');
[n,n]=size(A);
[V,D]=eig(A);%求得特征向量和特征值
            %求出最大特征值和它所对应的特征向量
tempNum=D(1,1);
pos=1;
for h=1:n
    if D(h,h)>tempNum
        tempNum=D(h,h);
        pos=h;
    end
end    
w=abs(V(:,pos));
w=w/sum(w);
t=D(pos,pos);
disp('准则层特征向量w=');disp(w);disp('准则层最大特征根t=');disp(t);
         %以下是一致性检验
CI=(t-n)/(n-1);RI=[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 1.60 1.61 1.615 1.62 1.63];
CR=CI/RI(n);
if CR<0.10
    disp('此矩阵的一致性可以接受!');
    disp('CI=');disp(CI);
    disp('CR=');disp(CR);
else disp('此矩阵的一致性验证失败,请重新进行评分!');
end


disp('请输入方案层各因素对准则层各因素权重的成对比较阵');
for i=1:n
    disp('请输入第');disp(i);disp('个准则层因素的判断矩阵B');disp(i);

需要参加数模竞赛的同学,可以看我的这个文章,会有最新的助攻哦:(大型比赛前会对名片进行更新)

  • 12
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值