基于 TOPSIS 的多指标综合评价模型

摘要

本文针对高考择校这一典型多指标决策问题,建立 TOPSIS(优劣解距离法)综合评价模型。模型包含四个步骤:识别指标类型并将各指标正向化;对正向化矩阵作向量归一化;构造理想最优解与理想最劣解并计算各方案到二者的加权欧氏距离;以贴近度作为综合评价依据。研究对象为四所候选学校,评价指标为师资、学费、班级人数与平均气温,四者分别属于极大型、极小型、中间型与区间型指标。求解得各校贴近度为:学校D 0.7788、学校C 0.5110、学校A 0.4899、学校B 0.4378,学校D 综合最优。分析表明:TOPSIS 倾向于选择各指标均无明显短板的方案,而非存在突出长板但短板明显的方案;权重作为外部输入,可与层次分析法或熵权法结合使用。

关键词:TOPSIS;正向化;理想解;贴近度;多指标评价


一、问题描述

某同学面临高考择校问题,需从四所候选学校中确定最终去向。评价指标共四项:

  • 师资:以量化分数表示;
  • 学费:以万元/年表示;
  • 班级人数:以人数表示,一般认为 40 人左右最为适宜;
  • 平均气温:以摄氏度表示,一般认为 16~18℃ 最为舒适。

原始数据如下:

师资学费(万)班级人数平均气温(℃)
学校A904.03515
学校B853.05021
学校C924.54019
学校D883.53817

要求建立综合评价模型,对四所学校排序并给出推荐。

二、模型假设

  1. 四项指标相互独立,不存在显著的交互影响;
  2. 各项指标数据真实可靠,不存在测量误差;
  3. 各指标均可量化,且其"最优"含义可由指标类型唯一确定;
  4. 班级人数与平均气温的最优取值分别为 40 人、区间 [16, 18]℃,由一般经验确定;
  5. 本模型先采用等权重进行初步评价,权重取值不影响模型结构。

三、符号说明

符号含义
$A$原始数据矩阵,$m \times n$
$m$方案(学校)个数
$n$指标个数
$\tilde{x}_{ij}$正向化后的指标值
$x_{best}$中间型指标的最优值
$[a,b]$区间型指标的最佳区间
$M$中间型/区间型指标正向化时的归一化因子
$z_{ij}$标准化后的指标值
$z_j^+$第 $j$ 个指标的理想最优解
$z_j^-$第 $j$ 个指标的理想最劣解
$w_j$第 $j$ 个指标的权重
$D_i^+$方案 $i$ 到理想最优解的加权距离
$D_i^-$方案 $i$ 到理想最劣解的加权距离
$S_i$方案 $i$ 的贴近度(综合得分)

四、模型建立与求解

4.1 指标类型识别

不同指标对"优"的定义方向不同,若直接比较会相互抵消,因此必须先统一方向。四个指标的类型判定如下:

指标类型判定依据
师资极大型(效益型)越高越好
学费极小型(成本型)越低越好
班级人数中间型越接近 40 人越好
平均气温区间型落在 [16, 18]℃ 最好

4.2 指标正向化

将各指标统一转化为"数值越大越优"。

(1)极大型指标:无需处理。

(2)极小型指标:

$$ \tilde{x} = \max(x) - x $$

(3)中间型指标($x_{best}$ 为最优值):

$$ \tilde{x} = 1 - \frac{|x - x_{best}|}{M}, \qquad M = \max_i |x_i - x_{best}| $$

(4)区间型指标($[a,b]$ 为最佳区间):

$$ \tilde{x} = \begin{cases} 1 - \dfrac{a - x}{M}, & x < a \\[6pt] 1, & a \le x \le b \\[6pt] 1 - \dfrac{x - b}{M}, & x > b \end{cases} \qquad M = \max\{a - \min(x),\ \max(x) - b\} $$

归一化因子 $M$ 的计算

  • 班级人数(中间型,$x_{best} = 40$):$|35-40|,\ |50-40|,\ |40-40|,\ |38-40|$ 的最大值为 $M = 10$;
  • 平均气温(区间型,$[a,b] = [16,18]$):$\max\{16-15,\ 21-18\} = 3$。

正向化结果

师资学费班级人数气温
A904.5−4.0 = 0.51−5/10 = 0.51−(16−15)/3 = 0.667
B854.5−3.0 = 1.51−10/10 = 01−(21−18)/3 = 0
C924.5−4.5 = 01−0/10 = 11−(19−18)/3 = 0.667
D884.5−3.5 = 11−2/10 = 0.817 ∈ [16,18] → 1

气温一项可说明区间型指标的特点:15℃ 与 19℃ 同样偏离最佳区间,正向化后均为 0.667,只有落入 16~18℃ 才取得满分。

4.3 数据标准化

正向化后各指标量纲仍不一致(师资为 80 量级,其余为 0~1 量级),采用向量归一化消除量纲影响:

$$ z_{ij} = \frac{\tilde{x}_{ij}}{\sqrt{\sum_{i=1}^{m} \tilde{x}_{ij}^{2}}} $$

标准化结果:

师资学费班级人数气温
A0.5068270.2672610.3636960.485071
B0.4786700.80178400
C0.51809000.7273930.485071
D0.4955640.5345220.5819140.727607

4.4 理想解构造与距离计算

取标准化矩阵各列的最大值构成理想最优解,最小值构成理想最劣解:

$$ z_j^+ = \max_i z_{ij}, \qquad z_j^- = \min_i z_{ij} $$

本问题中:

$$ z^+ = [0.518090,\ 0.801784,\ 0.727393,\ 0.727607] $$

$$ z^- = [0.478670,\ 0,\ 0,\ 0] $$

计算各方案到两个理想解的加权欧氏距离:

$$ D_i^+ = \sqrt{\sum_{j=1}^{n} w_j\left(z_{ij} - z_j^+\right)^2}, \qquad D_i^- = \sqrt{\sum_{j=1}^{n} w_j\left(z_{ij} - z_j^-\right)^2} $$

本文初步取等权重 $w_j = 0.25$。

学校$D_i^+$$D_i^-$
A0.3453040.331584
B0.5147980.400892
C0.4188320.437592
D0.1525610.537130

4.5 贴近度计算

$$ S_i = \frac{D_i^-}{D_i^+ + D_i^-} $$

$S_i \in [0,1]$,数值越大表示方案越优。

五、结果分析

学校贴近度 $S_i$排名
学校D0.7787981
学校C0.5109532
学校A0.4898653
学校B0.4378034

推荐学校D。 结合正向化结果分析各方案特征:

师资学费班级人数气温
A900.50.50.667
B851.500
C92010.667
D8810.81

(加粗表示该列最优值)

  • 学校C 在师资与班级人数两项均取得最优值,但平均气温为 19℃,未落入最佳区间;
  • 学校B 在班级人数(50 人)与平均气温(21℃)两项均为最低值,虽学费最为低廉,仍排名末位;
  • 学校D 没有任何一项取得最优值,但四项均处于较优水平,其 $D_i^+$ 仅为 0.1526,是四所学校中唯一低于 0.2 的。

结果表明:TOPSIS 倾向于选择各指标均无明显短板的方案,而非存在突出长板但短板明显的方案。 这是因为 $D_i^+$ 对任一指标的偏离都予以惩罚,短板越明显,距离理想解的加权距离越大。

六、模型评价

优点

  1. 充分利用原始数据信息,不依赖主观构造判断矩阵;
  2. 能够同时处理极大型、极小型、中间型与区间型四类指标,适用面广;
  3. 结果以贴近度形式给出,物理意义明确(与理想解的相对接近程度),便于排序;
  4. 计算过程完全可复现,不受决策者主观偏好影响(当权重取等权时)。

局限

  1. 权重需外部给定,本文采用等权重,未反映指标间的实际重要性差异;
  2. 理想解的构造依赖方案集本身,增加或删除备选方案可能导致排序变化;
  3. 采用欧氏距离,隐含各指标间线性无关的假设;
  4. 中间型与区间型指标的 $x_{best}$、$[a,b]$ 仍需经验确定,存在一定主观性。

改进方向

  1. 权重可结合层次分析法(AHP)由专家判断确定,或采用熵权法由数据离散程度客观确定,亦可将两者组合赋权;
  2. 可对权重作敏感性分析,检验排序结果的稳健性。

附录:Python 代码

"""
同学高考择校,从师资、学费、班级人数、城市气温等指标中考虑,决定最终去向
"""
import numpy as np

A = np.array(
    [
        [90, 4.0, 35, 15],
        [85, 3.0, 50, 21],
        [92, 4.5, 40, 19],
        [88, 3.5, 38, 17]
    ]
)

"""
        师资    学费    班级人数    平均气温
学校A    90     4.0      35         15
学校B    85     3.0      50         21
学校C    92     4.5      40         19
学校D    88     3.5      38         17
"""

# 因为师资肯定是越高越好。
# --> 所以:这是极大型指标
# 同理:学费是极小型指标
# 班级人数(40人合适):中间型指标
# 平均气温(维持在16-18度合适):区间型指标

"""
极大项指标           师资
极小项指标           学费
中间型指标           班级人数(最好40人),此时x_best = 40
区间型指标           年均气温(最好是 16 - 18 度)
"""

"""
注意⚠️ 中间型指标和区间型指标才有M,且计算公式不一样
"""

x_class_size_best = 40
temperature_a = 16
temperature_b = 18

# 先求出A的max min max-min
A_max_min_maxmin = np.array(
    [
        A.max(axis=0),
        A.min(axis=0),
        A.max(axis=0) - A.min(axis=0),
    ]
)

# 中间型指标和区间型指标的M
A_M = np.array(
    [
        max(np.abs(A[:, 2] - x_class_size_best)),
        max(temperature_a - np.min(A[:, 3]), max(A[:, 3]) - temperature_b)
    ]
)

print(A_max_min_maxmin)

print(A_M)


"""
第一步:矩阵正向化
"""
# 公式如下:
# 极大型指标:/
# 极小型指标:max - x     max:指标最大值 x:指标值
# 中间型指标:1 - |x_i - x_best| / M      x_best:最优值 x:指标值
"""
# 区间型指标:
                1 - (a - x_i) / M,  x_i < a
            =   1,                  a <= x_i <= b
                1 - (x_i - b) / M,  b < x_i
[a,b]为最佳区间,x_i为指标值
"""

# X是正向化后的矩阵(矩阵正向化)
X = np.column_stack([
    A[:, 0],
    np.max(A[:, 1]) - A[:, 1],
    1 - np.abs(A[:, 2] - x_class_size_best) / A_M[0],
    np.select(
        [
            A[:, 3] < temperature_a,
            (A[:, 3] >= temperature_a) & (A[:, 3] <= temperature_b),
            A[:, 3] > temperature_b,
        ],
        [
            1 - (temperature_a - A[:, 3]) / A_M[1],
            np.ones_like(A[:, 3]),
            1 - (A[:, 3] - temperature_b) / A_M[1],
        ]
    )
])

# 在这里先提前算好「矩阵标准化」要用的分母
Z = np.array(
    np.sqrt(np.sum(X ** 2, axis=0))
)

# 然后开始矩阵标准化
# Z是标准化矩阵(矩阵标准化)
Z = X / Z

print("原始矩阵正向化 X:")
print(X)
print("正向化矩阵标准化 Z:")
print(Z)

# 求出理想最优解(六边形战士)和理想最劣解

z_i_plus = np.max(Z, axis=0) # +

z_i_minus = np.min(Z, axis=0) # -

print("理想最优解:")
print(z_i_plus)
print("理想最劣解:")
print(z_i_minus)

"""
定权重(结合其他方法,例如:层次分析法、熵权法等)
"""

# 默认权重都是一样的
#             师资   学费  班级人数 气温
w = np.array([0.25, 0.25, 0.25, 0.25])


"""
计算各方案与最优解、最劣解的距离
"""


# 也就是每个方案(学校)的标「标准化矩阵」与最优解、最劣解的距离
D_plus = np.sqrt(np.sum(w * (Z - z_i_plus) ** 2, axis=1))

D_minus = np.sqrt(np.sum(w * (Z - z_i_minus) ** 2, axis=1))

D = np.column_stack([
    D_plus, D_minus
])

print("各方案与最优解、最劣解的距离")
print(D)


"""
计算最终得分
"""
"""
公式:

Si = (Di_minus) / (Di_plus + Di_minus)
"""

S = D_minus / (D_plus + D_minus)

print("最终得分")
print(S)

运行结果

[[92.   4.5 50.  21. ]
 [85.   3.  35.  15. ]
 [ 7.   1.5 15.   6. ]]
[10.  3.]
原始矩阵正向化 X:
[[90.          0.5         0.5         0.66666667]
 [85.          1.5         0.          0.        ]
 [92.          0.          1.          0.66666667]
 [88.          1.          0.8         1.        ]]
正向化矩阵标准化 Z:
[[0.50682714 0.26726124 0.36369648 0.48507125]
 [0.47867008 0.80178373 0.         0.        ]
 [0.51808997 0.         0.72739297 0.48507125]
 [0.49556432 0.53452248 0.58191437 0.72760688]]
理想最优解:
[0.51808997 0.80178373 0.72739297 0.72760688]
理想最劣解:
[0.47867008 0.         0.         0.        ]
各方案与最优解、最劣解的距离
[[0.34530414 0.33158356]
 [0.51479759 0.40089186]
 [0.41883191 0.43759244]
 [0.15256146 0.53713029]]
最终得分
[0.48986495 0.4378033  0.51095282 0.77879761]