层次分析法(AHP)机理方法¶
一、AHP 的核心数学机制(简要)¶
- 判断矩阵 A:
满足 $a_{ij} = 1/a_{ji}$,且 $a_{ii}=1$ - 权重向量 w:
常用方法:- 最大特征值法(Eigenvalue Method)
- 几何平均法(Geometric Mean)
- 一致性检验:
$$ CI=\frac{\lambda_{\max}-n}{n-1},\quad CR=\frac{CI}{RI} $$ 若 $CR<0.1$,一致性可接受。
In [ ]:
Copied!
import numpy as np
def ahp_eigen(matrix):
"""
使用最大特征值法计算权重
"""
matrix = np.array(matrix, dtype=float)
n = matrix.shape[0]
# 特征值分解
eigvals, eigvecs = np.linalg.eig(matrix)
max_index = np.argmax(eigvals.real)
w = eigvecs[:, max_index].real
w = w / w.sum()
# 最大特征值
lambda_max = eigvals[max_index].real
return w, lambda_max
import numpy as np
def ahp_eigen(matrix):
"""
使用最大特征值法计算权重
"""
matrix = np.array(matrix, dtype=float)
n = matrix.shape[0]
# 特征值分解
eigvals, eigvecs = np.linalg.eig(matrix)
max_index = np.argmax(eigvals.real)
w = eigvecs[:, max_index].real
w = w / w.sum()
# 最大特征值
lambda_max = eigvals[max_index].real
return w, lambda_max
✅ 一致性检验函数¶
In [ ]:
Copied!
def consistency_check(matrix, lambda_max):
n = len(matrix)
RI_dict = {
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
}
CI = (lambda_max - n) / (n - 1)
CR = CI / RI_dict[n]
return CI, CR
def consistency_check(matrix, lambda_max):
n = len(matrix)
RI_dict = {
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
}
CI = (lambda_max - n) / (n - 1)
CR = CI / RI_dict[n]
return CI, CR
✅ 内部机制说明¶
np.linalg.eig求解主特征向量 → 归一化后即为权重- 数学依据:Perron–Frobenius 定理
- 适用于理论严谨、学术研究场景
三、方法二:几何平均法(计算快、稳定)¶
✅ 函数实现¶
def ahp_geometric_mean(matrix):
"""
几何平均法计算权重
"""
matrix = np.array(matrix, dtype=float)
n = matrix.shape[0]
# 每一行几何平均
geo_mean = np.exp(np.mean(np.log(matrix), axis=1))
weights = geo_mean / geo_mean.sum()
return weights
✅ 内部机制说明¶
- 对判断矩阵按行取几何平均: $$ w_i = \frac{\left(\prod_j a_{ij}\right)^{1/n}}{\sum_k \left(\prod_j a_{kj}\right)^{1/n}} $$
- 优点:
- 无需特征值计算
- 数值稳定性好
- 缺点:
- 理论上不如特征值法严谨
✅ 工程推荐
五、方法四:面向对象封装(工程级写法)¶
✅ AHP 类¶
class AHP:
def __init__(self, matrix):
self.A = np.array(matrix, dtype=float)
self.n = self.A.shape[0]
def weights(self, method="eigen"):
if method == "eigen":
return self._eigen()
elif method == "geo":
return self._geometric()
else:
raise ValueError("Unknown method")
def _eigen(self):
eigvals, eigvecs = np.linalg.eig(self.A)
idx = np.argmax(eigvals.real)
w = eigvecs[:, idx].real
return w / w.sum()
def _geometric(self):
gm = np.exp(np.mean(np.log(self.A), axis=1))
return gm / gm.sum()
def check_consistency(self):
w = self._eigen()
Aw = self.A @ w
lambda_max = np.mean(Aw / w)
CI = (lambda_max - self.n) / (self.n - 1)
RI = [0, 0, 0.58, 0.90, 1.12, 1.24, 1.32, 1.41, 1.45][self.n - 1]
return CI, CI / RI
✅ 使用示例¶
matrix = [
[1, 3, 5],
[1/3, 1, 2],
[1/5, 1/2, 1]
]
ahp = AHP(matrix)
w = ahp.weights(method="geo")
CI, CR = ahp.check_consistency()
六、四种方法对比总结¶
| 方法 | 精度 | 速度 | 适用场景 |
|---|---|---|---|
| 特征值法 | ⭐⭐⭐⭐ | ⭐⭐ | 学术、严格建模 |
| 几何平均 | ⭐⭐⭐⭐ | ⭐⭐⭐⭐ | 工程实践(推荐) |
| 列和归一化 | ⭐⭐⭐ | ⭐⭐⭐⭐ | 教学、快速验证 |
| OOP 封装 | ⭐⭐⭐⭐ | ⭐⭐⭐ | 大型项目 |
In [ ]:
Copied!