层次分析法模型

本文最后更新于 2025年7月28日 上午

怎么能让指标在同一数量级,且保证在同一指标下其差距不变?

归一化处理:数组[a, b, c] -> $\frac{a}{a+b+c}, \frac{b}{a+b+c}, \frac{c}{a+b+c}$,再调整各自的权重

层次分析法(AHP)

模型原理:

将问题分成三个层次:最高层(结果),中间层,最底层(决策提供的方案 )

基本步骤

1. 建立递阶层次结构模型

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

  • 对指标的重要性进行两两比较,构造判断矩阵,从而科学地求出权重
  • 矩阵中$a_{ij}$的含义:第$i$个指标相对于第$j$个指标的重要程度
标度 含义
1 表示两个因素相比,具有同样重要性
3 表示两个因素相比,一个因素比另一个因素稍微重要
5 表示两个因素相比,一个因素比另一个因素明显重要
7 表示两个因素相比,一个因素比另一个因素强烈重要
9 表示两个因素相比,一个因素比另一个因素极端重要
2, 4, 6, 8 上述两相邻判断的中值

如果每次都只是两两比较,最后可能产生矛盾,这时需要一致性检验

正负反矩阵:$a_{ij}>0且a_{ij} \times a_{ji}=1且各行各列成比例$

一致矩阵:若正负反矩阵满足$a_{ik} \times a_{kj}=a_{ij}$,则为一致矩阵

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

3. 求权重(得到最后的权重向量)

套板子就行)

  • 几何平均法求权重
  • 算术平均法求权重
  • 特征值法求权重

层次分析法 python代码 (ai)

代码PYTHON · 159 行
import numpy as np

class AHP:
    """
    使用 Python 实现层次分析法 AHP
    """

    def __init__(self, criteria, judgment_matrix):
        """
        初始化 AHP 类
        :param criteria: list, 评价准则的名称列表
        :param judgment_matrix: np.ndarray, 判断矩阵
        """
        self.criteria = criteria
        self.matrix = np.array(judgment_matrix)
        self.n = self.matrix.shape[0]

        # 随机一致性指标 RI 表
        self.RI = {
            1: 0, 2: 0, 3: 0.58, 4: 0.90, 5: 1.12, 6: 1.24, 7: 1.32,
            8: 1.41, 9: 1.45, 10: 1.49, 11: 1.51, 12: 1.48, 13: 1.56,
            14: 1.57, 15: 1.59
        }

    def _check_consistency(self, max_eigenvalue):
        """
        一致性检验
        公式: CR = CI / RI,  CI = (λ_max - n) / (n - 1)
        """
        CI = (max_eigenvalue - self.n) / (self.n - 1)

        # 当 n <= 2 时,判断矩阵总是一致的
        if self.n <= 2:
            CR = 0
        else:
            try:
                CR = CI / self.RI[self.n]
            except KeyError:
                print(f"警告: 矩阵大小 n={self.n} 超出预设的 RI 表范围,无法计算 CR。")
                CR = float('nan')  # Not a Number

        print("\n--- 一致性检验 ---")
        print(f"最大特征值 λ_max = {max_eigenvalue:.4f}")
        print(f"一致性指标 CI = {CI:.4f}")
        if self.n > 2:
            print(f"随机一致性指标 RI = {self.RI.get(self.n, 'N/A')}")
            print(f"一致性比率 CR = {CR:.4f}")

        if CR < 0.10:
            print("结果: 判断矩阵通过一致性检验。")
            return True
        else:
            print(f"结果: 判断矩阵未通过一致性检验 (CR = {CR:.4f} >= 0.10),建议修正判断矩阵。")
            return False

    def arithmetic_mean_method(self):
        """
        算术平均法求权重
        1. 将判断矩阵按列归一化
        2. 将归一化后的矩阵按行求和
        3. 将行和向量归一化得到权重向量
        """
        # 1. 按列归一化
        col_sum = np.sum(self.matrix, axis=0)
        normalized_matrix = self.matrix / col_sum

        # 2. 按行求和
        row_sum = np.sum(normalized_matrix, axis=1)

        # 3. 归一化得到权重
        weights = row_sum / self.n

        print("\n--- 1. 算术平均法 (Arithmetic Mean Method) ---")
        for i, w in enumerate(weights):
            print(f"  {self.criteria[i]:<10}: {w:.4f}")
        return weights

    def geometric_mean_method(self):
        """
        几何平均法求权重
        1. 计算判断矩阵每行元素的几何平均数
        2. 将得到的向量归一化
        """
        # 1. 计算每行乘积
        row_product = np.prod(self.matrix, axis=1)

        # 2. 计算 n 次方根
        root = np.power(row_product, 1 / self.n)

        # 3. 归一化得到权重
        weights = root / np.sum(root)

        print("\n--- 2. 几何平均法 (Geometric Mean Method) ---")
        for i, w in enumerate(weights):
            print(f"  {self.criteria[i]:<10}: {w:.4f}")
        return weights

    def eigenvalue_method(self):
        """
        特征值法求权重
        1. 求出判断矩阵的最大特征值及其对应的特征向量
        2. 对特征向量进行归一化处理
        """
        # 1. 计算特征值和特征向量
        eigenvalues, eigenvectors = np.linalg.eig(self.matrix)

        # 2. 找到最大特征值及其索引
        max_eigenvalue_index = np.argmax(eigenvalues)
        max_eigenvalue = np.real(eigenvalues[max_eigenvalue_index])

        # 3. 提取对应的特征向量
        eigenvector = np.real(eigenvectors[:, max_eigenvalue_index])

        # 4. 归一化权重向量
        weights = eigenvector / np.sum(eigenvector)

        print("\n--- 3. 特征值法 (Eigenvalue Method) ---")
        for i, w in enumerate(weights):
            print(f"  {self.criteria[i]:<10}: {w:.4f}")

        # 进行一致性检验
        self._check_consistency(max_eigenvalue)

        return weights, max_eigenvalue


if __name__ == '__main__':
    # --- 示例 ---
    # 假设需要选择一个旅游目的地,考虑四个准则:
    # C1: 景色
    # C2: 费用
    # C3: 交通
    # C4: 饮食
    criteria_names = ['景色', '费用', '交通', '饮食']

    # 构建判断矩阵 A
    # A[i, j] 表示准则 i 相对于准则 j 的重要性
    # 例如 A[0, 1] = 3 表示 "景色" 比 "费用" '稍重要'
    judgment_matrix = [
        [1, 3, 4, 2],
        [1 / 3, 1, 2, 1 / 2],
        [1 / 4, 1 / 2, 1, 1 / 3],
        [1 / 2, 2, 3, 1]
    ]

    # 实例化 AHP
    ahp_solver = AHP(criteria=criteria_names, judgment_matrix=judgment_matrix)

    # 分别使用三种方法计算权重
    w_arithmetic = ahp_solver.arithmetic_mean_method()
    w_geometric = ahp_solver.geometric_mean_method()
    # 特征值法会同时进行一致性检验
    w_eigen, lambda_max = ahp_solver.eigenvalue_method()

    print("\n--- 最终权重对比 ---")
    print(f"{'准则':<10} {'算术平均法':<12} {'几何平均法':<12} {'特征值法':<12}")
    print("-" * 50)
    for i in range(len(criteria_names)):
        print(f"{criteria_names[i]:<10} {w_arithmetic[i]:<12.4f} {w_geometric[i]:<12.4f} {w_eigen[i]:<12.4f}")