评价类问题
评价类问题
主观评价
层次分析法(AHP)
层次分析法通常有三层:目标层,准则层和方案层。所要解决的问题是方案层对目标层的权重问题。具体步骤如下:
-
针对准则层,构造判断矩阵 \(A\),其满足 \(a_{ij} = \frac{1}{a_{ji}}\) 。矩阵元素用 \(Saaty\) 的 1-9 标度方法给出。
由于该矩阵的特征值等严重依赖于主观,因此必须进行一致性检验:
- 定义一致性指标 \(CI = \frac{\lambda_{max} - n}{n-1}\) ,平均随机一致性指标 \(RI\)
阶数 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 \(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 - 计算一致性比例 \(CR = \frac{CI}{RI}\)。当 \(CR < 0.1\) 时我们认为可以接受,反之需要调整。
-
对于评价矩阵 \(A\),寻找其特征向量 \(w\) 满足 \(Aw = \lambda_{max}w\) ,将其归一化后作为评价指标,称为计算排序向量的特征根法。
-
对于方案层,不同的方案对每一个评价指标,均可以列出一个评价矩阵 \(B_i\),同样可以求出其最大特征根下的归一化后的特征向量 \(b_i\) 。
-
对于 \(n\) 个不同的评价指标,共可以找出 n 个特征向量组成矩阵 \(B = (b_1,...,b_n)\) ,计算后有列向量 \(R = B w\) 。
-
列向量 \(R\) 中第几列的元素值最大,则对应选择那一个方案最优。
附代码:
import numpy as np
RI = [0, 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]
def cal_max_eig(A):
w, v = np.linalg.eig(A)
max_lambda = np.real(np.max(w))
position = np.argmax(w)
max_eig = np.real(v[:, position])
max_eig = max_eig / sum(max_eig)
print('最大特征值为: ', max_lambda)
print('所求权重为: ', max_eig)
(n, n) = np.shape(A)
CI = (max_lambda - n) / (n - 1)
CR = CI / RI[n]
print('一致性检验:CR = ', CR, end=', ')
if CR < 0.1:
print('可以接受 ^_^')
else:
print('不可以接受 Q^Q')
return max_eig
def find_max(B, w):
w = np.mat(w).T
res = np.dot(B, w)
print('最后结果为:\n', res)
max_num = np.argmax(res)
print('应该选择第 {0} 号方案'.format(max_num + 1))
实际上, \(AHP\) 由于主观性过强,因此最好不要使用。如果非要使用的话,一些指标最好有数据来源,这些必须要在文章中单独说明。而且其选择较为粗略,只能选择最优的一个,不能得到更好的方案,同时面对一些高精度的问题时也显得有些无能为力。
模糊综合评价法(FCE)
实际世界中许多现象和关系具有不确定性,为了对这类模糊现象进行研究与处理,我们引入了模糊数学方法。具体步骤为:
-
确定 \(m\) 个评价指标和 \(n\) 个评价等级,构建模糊综合评价矩阵 \(R = (r_{ij})_{m \times n}\) 。
-
确定评价指标的权重。通常有主观和客观两类,而客观里又常用质量分数法和变异系数法。
变异系数法:若某项指标的数值差异较大,则认为其包含的分辨信息更丰富,能明确区分开各评价对象。
- 计算第 \(i\) 项指标的均值与方差: \(\bar{x_i} = \frac{1}{n} \sum_{j=1}^n a_{ij}\), \(s_i^2 = \frac{1}{n-1}\sum_{j = 1}^{n}(a_{ij} - \bar{x_i})^2\) 。
- 令 \(v_i = \frac{s_i}{|\bar{x_i}|}\) ,则归一化后的 \(v_i\) 即为各项指标的权重,即 \(w_i = \frac{v_i}{\sum v_i}\)
PS:用这种方法求出的某指标的权重和该指标在评价体系中的重要性是两个概念。
-
对其进行模糊合成与综合评价。其中主因素突出型适用于模糊矩阵中数据相差很悬殊的情形,而加权平均型则常用于因素很多的时候,可以避免信息丢失。在此给出常用的模糊合成算子有:
特点 \(M(\wedge, \vee)b_j = \underset{i=1}{\overset{m}{\vee}}(a_i \wedge r_{ij})\) \(M(\cdot, \vee)b_j = \underset{i=1}{\overset{m}{\vee}}(a_i \cdot r_{ij})\) \(M(\wedge, +)b_j=\underset{i=1}{\overset{m}{\sum}}(a_i \wedge r_{ij})\) \(M(\cdot, +)b_j = \underset{i=1}{\overset{m}{\sum}}(a_i \cdot r_{ij})\) 体现权数作用 不明显 明显 不明显 明显 综合程度 弱 弱 强 强 利用 \(R\) 的信息 不充分 不充分 比较充分 充分 类型 主因素突出型 主因素突出型 加权平均型 加权平均型 -
之后得到了模糊综合评价向量 \(B\),归一化后的 \(b_j\) 可以理解为评价对象对第 \(j\) 等级的隶属度。之后利用最大隶属度法或加权平均法对其进行分析即可。
后附有代码:
import numpy as np
def coefficient_of_variation(R):
R = np.array(R)
(m, n) = np.shape(R)
avg_x = R.sum(axis=1) / n # 计算均值
s2 = np.std(R, axis=1, ddof=1) # 计算标准差
v = s2 / np.absolute(avg_x) # 计算权向量
w = v / v.sum() # 归一化
return w
def M_wedge_vee(R, a): # 四种合成算子
R = np.array(R)
(m, n) = np.shape(R)
B = list()
for j in range(n):
temp = min(R[0][j], a[0])
for i in range(m):
temp = max(temp, min(R[i][j], a[i]))
B.append(temp)
return B
def M_multi_vee(R, a): # 四种合成算子
R = np.array(R)
(m, n) = np.shape(R)
B = list()
for j in range(n):
temp = R[0][j] * a[0]
for i in range(m):
temp = max(temp, R[i][j] * a[i])
B.append(temp)
return B
def M_wedge_add(R, a): # 四种合成算子
R = np.array(R)
(m, n) = np.shape(R)
B = list()
for j in range(n):
temp = 0
for i in range(m):
temp = temp + min(R[i][j], a[i])
B.append(temp)
return B
def M_multi_add(R, a): # 四种合成算子
R = np.array(R)
(m, n) = np.shape(R)
return [sum(R[:, i], a) for i in range(n)]
灰色关联分析法(GRA)
给出关联系数表达式:
其中数据序列要求是无量纲序列,这里的 \(P\) 常取值为 0.5。给出代码:
import numpy as np
import pandas as pd
def dimensionlessProcessing(df): # 无量纲化
newDataFrame = pd.DataFrame(index=df.index)
columns = df.columns.tolist()
for c in columns:
d = df[c]
MAX = d.max()
MIN = d.min()
MEAN = d.mean()
newDataFrame[c] = ((d - MEAN) / (MAX - MIN)).tolist()
return newDataFrame
def GRA_ONE(gray, m=0):
gray = dimensionlessProcessing(gray)
std = gray.iloc[:, m] # 标准化为标准要素
gray.drop(str(m), axis=1, inplace=True)
ce = gray.iloc[:, 0:] # 为比较要素
shape_n, shape_m = ce.shape[0], ce.shape[1] # 计算行列
# 与标准要素比较,相减
a = np.zeros([shape_m, shape_n])
for i in range(shape_m):
for j in range(shape_n):
a[i, j] = abs(ce.iloc[j, i] - std[j])
# 取出矩阵中最大值与最小值
c, d = np.amax(a), np.amin(a)
# 计算值
result = np.zeros([shape_m, shape_n])
for i in range(shape_m):
for j in range(shape_n):
result[i, j] = (d + 0.5 * c) / (a[i, j] + 0.5 * c)
# 求均值,得到灰色关联值,并返回
result_list = [np.mean(result[i, :]) for i in range(shape_m)]
result_list.insert(m, 1)
return pd.DataFrame(result_list)
def GRA(DataFrame):
df = DataFrame.copy()
list_columns = [str(s) for s in range(len(df.columns)) if s not in [None]]
df_local = pd.DataFrame(columns=list_columns)
df.columns = list_columns
for i in range(len(df.columns)):
df_local.iloc[:, i] = GRA_ONE(df, m=i)[0]
return df_local
客观评价
主成分分析法(PCA)
多元统计分析处理的是多变量(多指标)问题。在实际问题中,有可能变量较多,而变量之间又存在一定信息的交叉。因此我们想通过这种方式找到较少的变量来代替原来的多变量,也算是一种 "降维" 的思想。具体讲解可参考网站。假设原来有 \(p\) 个指标,我们希望对这 \(p\) 个指标进行线性组合找到新的 \(k(k \le p)\) 个指标:
基于协方差矩阵
- 对某个问题, \(X\) 的协方差矩阵往往是未知的,可以用估计来代替:\(\hat{\sum_{x}} = [\frac{1}{n-1} \sum_{l=1}^n(x_{il} - \bar{x_i})(x_{jl} - \bar{x_j})]_{p \times p}\)
- 由协方差矩阵求出其特征根 \(\lambda_1 \ge \lambda_2 \ge \cdots \ge \lambda_p \ge 0\)。
- 分别求出不同特征根对应的特征向量 \(U_i\) ,则有 \(F_i = U_i^TX\)
- 计算所选出的 \(k\) 个主成分的得分,带入原始数据的中心化值 \(X_i^* = X_i - \bar{X} = (x_{1i}-\bar{x_1}, x_{2i}-\bar{x_2}, \cdots,x_{pi} - \bar{x_p})^T\) 计算得分后按照分值大小排队
基于相关系数矩阵
如果各个变量之间拥有不同的量纲,则必须基于相关系数矩阵进行主成分分析。不同的是计算得分是应该采用标准化后的数据。
- 计算相关系数矩阵: \(r_{xy} = \frac{n \sum x_iy_i - \sum x_i \sum y_i}{\sqrt{n \sum x_i^2 - (\sum x_i)^2} \sqrt{x \sum y_i^2} - (\sum y_i)^2}\)
值得注意的一点是,不论选择哪种矩阵,都是一个实对称矩阵,而且都一定是一个非负定矩阵,因此不会出现特征值小于零的情况。
import numpy as np
def normalize(X): # 标准化数据矩阵
X = np.array(X) # X 为 n * m 矩阵,有 n 个指标,每个指标有 m 个数据
d_X = (X - np.mean(X, axis=1)) / np.std(X, axis=1, ddof=1)
return d_X
def cal_Cov(X):
return np.cov(X, rowvar=True) # rowvar=True 意为对每一行作为独立变量
def cal_R(X):
return np.corrcoef(X) # 计算所有行的相关系数
def cal_eig(X):
X = np.array(X)
w, v = np.linalg.eig(X)
w_sum = w.sum()
new_W = list()
for idx, wi in enumerate(w):
new_W.append([wi, idx])
new_W.sort(reverse=True) # 从大到小排序特征值
w_now = 0
idx = 0
for [w, i] in new_W:
w_now = w_now + w
idx = idx + 1
print('第 {0} 个特征值为 {1},特征向量'.format(idx, round(w, 6)), v[:, i], end=' ')
print('信息贡献率为 {0},累积贡献率为 {1}'.format(round(w / w_sum, 5), round(w_now / w_sum, 5)))
因子分析法(FAM)
其实与主成分分析法类似,在主成分的基础上实现了对因子的旋转,更加易于解释。
逼近理想解排序(Topsis)法
\(\text{TOPSIS}\) 法是一种常用的组内综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。基本过程为基于归一化后的原始数据矩阵,采用余弦法找出有限方案中的最优方案和最劣方案,然后分别计算各评价对象与最优方案和最劣方案间的距离,获得各评价对象与最优方案的相对接近程度,以此作为评价优劣的依据。该方法对数据分布及样本含量没有严格限制,数据计算简单易行。详解
一般来说,如果我们想评价一个事物的好坏,有两种想法:
- 基于分布的评价方法。观察某个样本的水平在整体的那个区间内。但是这样只能给出单向的结果。例如只能给出其在前 5% 左右。而且当遇到大量数据重合的时候将会无能为力。
- 第二种想法是参考极差。不仅仅考虑最大值还去考虑最小值,去看当前样本在的位置
距离两个极端的远近来衡量。
既然要涉及到距离,那么对于多个指标下,我们就有必要去统一衡量距离这件事。一般来说指标分为以下四类:
| 指标名称 | 指标特点 | 举个栗子 |
|---|---|---|
| 极大型(效益型)指标 | 越大(多)越好 | 成绩,GPA 增速,企业利润 |
| 极小型(成本型)指标 | 越小(少)越好 | 费用,坏品率,污染程度 |
| 中间型指标 | 越接近中间某个值越好 | 水质评估时的 PH 值 |
| 区间型指标 | 落在某个区间内最好 | 体温,水中植物的营养均量 |
对于不同的指标,我们需要拿其和最优值作对比得到距离的定量描述。换句话说,意味着我们有四种不同的定量计算方式,而这在多指标下是很容易混乱,极其可怕的一件事。因此我们选择将指标统一化为极大型指标数据,具体统一措施有:
- 极小型数据指标正向化处理:\(\hat{x_i} = max_x - x_i\),如果全部为正数,也可以使用 \(\hat{x_i} = \frac{1}{x_i}\)
- 中间型数据指标正向化处理:假设最佳数值是 \(x_{best}\),取区间长度 \(M = max\{|x_i - x_{best}|\}\),有 \(\hat{x_i} = 1 - \frac{x_i - x_{best}}{M}\)
- 区间型数据指标正向化处理:假设最佳区间是 \([a,b]\),取区间长度 \(M = max\{a - min\{x_i\},max\{x_i\}-b\}\) ,有 \(\hat{x_i} = \begin{cases}1 - \frac{a - x_i}{M},x_i < a \\ 1, a < x_i < b \\ 1 - \frac{x_i-b}{M},x_i>b\end{cases}\)
另一个问题是,不同的指标之间涉及到一个量纲不同的问题,我们需要首先对数据进行标准化处理:即用每一列元素除以当前列向量的范数(使用余弦距离度量)。
整体的算法评价过程是:
- 指标同向话,一般选取指标正向化
- 构造归一化初始矩阵
- 确定最优方案和最劣方案,即把每一个指标的最优解和最劣解取出来构造出两个新的方案
- 计算各评价对象到两个方案之间的欧几里得距离,即 \(D_i^+,D_i^-\) ,最后给出与最优方案的贴近程度: \(C_i = \frac{D_i^-}{D_i^+ + D_i^-}\)
- 根据贴近程度排序后给出评价结果

浙公网安备 33010602011771号