优劣解距离法topsis模型

前言

TOPSIS 法是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。

原理

基本过程为先将原始数据矩阵统一指标类型(一般正向化处理)得到正向化的矩阵,再对正向化的矩阵进行标准化处理以消除各指标量纲的影响,并找到有限方案中的最优方案和最劣方案,然后分别计算各评价对象与最优方案和最劣方案间的距离,获得各评价对象与最优方案的相对接近程度,以此作为评价优劣的依据。该方法对数据分布及样本含量没有严格限制,数据计算简单易行。

优劣解距离法步骤

第一步:将原始矩阵正向化

常见的四种指标

指标名称 指标特点 例子
极大型(效益型)指标 越大(多)越好 成绩,GDP增速,利润
极小型(成本型)指标 越小(少)越好 费用,坏平率,污染程度
中间型指标 越接近某个值越好 水质量的pH值
区间型指标 落在某个区间最好 体温
所谓的将原始矩阵正向化,就是要将所有的指标类型统一转化为极大型指标

极小型指标转化为极大型指标的公式为$$x_{\max}-x_i$$

# 极小型指标 -> 极大型指标
def dataDirection_1(datas):
    return np.max(datas) - datas
中间型指标

指标值既不要太大也不要太小,取某特定值最好(如水质量评估 PH 值)

\(\left\{ \left. x_i \right\} \right. \)是一组中间型指标序列,且最佳的数值为\(x_{best}\),正向化公式为:

优劣解距离法topsis模型

# 中间型指标 -> 极大型指标
def dataDirection_2(datas, x_best):
    temp_datas = datas - x_best
    M = np.max(abs(temp_datas))
    answer_datas = 1 - abs(datas - x_best) / M
    return answer_datas
区间型指标

指标值落在某个区间内最好,例如人的体温在36°~37°这个区间比较好

\(\left\{ \left. x_i \right\} \right. \)是一组区间型指标序列,且最佳的区间为[a,b],正向化公式为:
优劣解距离法topsis模型

# 区间型指标 -> 极大型指标
def dataDirection_3(datas, x_min, x_max):
    M = max(x_min - np.min(datas), np.max(datas) - x_max)
    answer_list = []
    for i in datas:
        if (i < x_min):
            answer_list.append(1 - (x_min - i) / M)
        elif (x_min <= i <= x_max):
            answer_list.append(1)
        else:
            answer_list.append(1 - (i - x_max) / M)
    return np.array(answer_list)

正向化的公式不唯一,可以结合自己的数据进行适当的修改。

第二步:正向化矩阵标准化

标准化的目的是消除不同指标量纲的影响

假设有n个评价对象,m个评价指标(已经正向化了)构成的正向化矩阵如下:
优劣解距离法topsis模型

那么对其标准化矩阵记为Z,那么对于Z中的每一个元素有:
优劣解距离法topsis模型

# 正向化矩阵标准化
def temp2(datas):
    K = np.power(np.sum(pow(datas, 2), axis=1), 0.5)
    for i in range(0, K.size):
        for j in range(0, datas[i].size):
            datas[i, j] = datas[i, j] / K[i]  # 套用矩阵标准化的公式
    return datas

注意:标准化的方法有很多种,其主要目的就是去除量纲的影响

第三步:计算得分并归一化

计算评分公式

$$
\frac{x_i-x_{\min}}{x_{\max}-x_{\min}}=\frac{x_i-x_{\min}}{\left( x_{\max}-x_i \right) +\left( x_i-x_{\min} \right)}
$$

定义最大值:

优劣解距离法topsis模型

定义最小值:

优劣解距离法topsis模型

定义第\(i\left( i=1,2,\cdots ,n \right)\)个评价对象与最大值的距离:

$$
D_{i}^{+}=\sqrt{\sum_{j=1}^m{\left( Z_{j}^{+}-z_{ij} \right) ^2}}
$$

定义第\(i\left( i=1,2,\cdots ,n \right)\)个评价对象与最小值的距离:

$$
D_{i}^{-}=\sqrt{\sum_{j=1}^m{\left( Z_{j}^{-}-z_{ij} \right) ^2}}
$$

那么我们就可以算出第\(i\left( i=1,2,\cdots ,n \right)\)个评价对象未归一化的得分:$$S_i=\frac{D_{i}^{-}}{D_{i}^{+}+D_{i}^{-}}$$

注意:这里还没有考虑指标的权重,我们可以使用层次分析法给评价指标确定权重;层次分析法的主观性太强了,更推荐使用熵权法来进行客观赋值

很明显\(0\le S_i\le 1\)且\(S_i\)越大,\(D_{i}^{+}\)越小,即越接近最大值

将得分归一化:

优劣解距离法topsis模型

# 计算得分并归一化
def temp3(answer2):
    list_max = np.array(
        [np.max(answer2[0, :]), np.max(answer2[1, :]), np.max(answer2[2, :]), np.max(answer2[3, :])])  # 获取每一列的最大值
    list_min = np.array(
        [np.min(answer2[0, :]), np.min(answer2[1, :]), np.min(answer2[2, :]), np.min(answer2[3, :])])  # 获取每一列的最小值
    max_list = []  # 存放第i个评价对象与最大值的距离
    min_list = []  # 存放第i个评价对象与最小值的距离
    answer_list = []  # 存放评价对象的未归一化得分
    for k in range(0, np.size(answer2, axis=1)):  # 遍历每一列数据
        max_sum = 0
        min_sum = 0
        for q in range(0, 4):  # 有四个指标
            max_sum += np.power(answer2[q, k] - list_max[q], 2)  # 按每一列计算Di+
            min_sum += np.power(answer2[q, k] - list_min[q], 2)  # 按每一列计算Di-
        max_list.append(pow(max_sum, 0.5))
        min_list.append(pow(min_sum, 0.5))
        answer_list.append(min_list[k] / (min_list[k] + max_list[k]))  # 套用计算得分的公式 Si = (Di-) / ((Di+) +(Di-))
        max_sum = 0
        min_sum = 0
    answer = np.array(answer_list)  # 得分归一化
    return (answer / np.sum(answer))
注意:要区别开归一化和标准化。归一化的计算步骤也可以消去量纲的影响,但更多时候,我们进行归一化的目的是为了让我们的结果更容易解释,或者说让我们对结果有一个更加清晰直观的印象。例如将得分归一化后可限制在0‐1这个区间,对于区间内的每一个得分,我们很容易的得到其所处的比例位置。
发表评论 取消回复
表情 图片 链接 代码

分享