C. L.Hwang和 K.Yoon于1981年首次提出 TOPSIS(Technique for Order Preference by Similarity to an Ideal Solution),可翻译为逼近理想解排序法,国内常简称为优劣解距离法。
TOPSIS法是一种常用的综合评价方法,能充实利用原始数据的信息,其效果能正确地反映各评价方案之间的差距。
TOPSIS法引入了两个基本概念:
计算得分并归一化
S i = D i − D i + + D i − S_{i}=\frac{D_{i}^{-}}{D_{i}^{+}+D_{i}^{-}} Si=Di++Di−Di−,此中 S i S_{i} Si为得分, D i + {D_{i}^{+}} Di+为评价对象与最大值的距离, D i − D_{i}^{-} Di−
常见的指标范例:
指标名称指标特点例子极大型 (效益型) 指标越大(多)越好成绩、 GDP增速、 企业利润极小型 (本钱型) 指标越小(少)越好费用、 坏品率、污染程度中心型指标越接近某个值越好水质量评估时的PH值区间型指标落在某个区间最好体温、 水中植物性营养物量 在 TOPSIS 方法中,就是要将全部指标举行同一正向化,即同一转化为极大型指标。 那么就必要极小型、中心型以及区间型的指标举行转化为极大型指标。
指标名称公式极大型(效益型)指标/极小型(本钱型)指标 x ~ = m a x − x \tilde{x} = max-x x~=max−x, x ~ \tilde{x} x~为指标值, m a x max max为指标最大值, x x x为指标值中心型指标 { x i } \{x_i\} {xi} 是一组中心型序列,最优值是 x b e s t x_{best} xbest,$M = max{区间型指标 x i {x_i} xi是一组区间型序列,最佳区间为 [ a , b ] [a,b] [a,b],正向化公式如下 M = m a x { a − m i n { x i } , m a x { x i } − b } , x ~ i = { 1 − a − x i M , x i < a 1 , a ≤ x i ≤ b 1 − x i − b M , x i > b M=max\{a-min\{x_i\}, max\{x_i\}-b\}, \widetilde{x}_i=\begin{cases}1-\frac{a-x_i}{M}, x_i<a\\1, a\leq x_i\leq b\\1-\frac{x_i-b}{M}, x_i>b\end{cases} M=max{a−min{xi},max{xi}−b},x i=⎩ ⎨ ⎧1−Ma−xi,xi<a1,a≤xi≤b1−Mxi−b,xi>b
颜值为极大型指标
脾气为极小型指标
候选人颜值 m a x max max m a x − x max-x max−xA10100B7103C3107
身高为中心型指标
候选人身高 x b e s t x_{best} xbest| x i − x b e s t x_i-x_{best} xi−xbest| x ^ i \hat{x}_i x^iA175165101B16416511/10C15716588/10
体重为区间型指标
候选人体重 M M M x ^ i \hat{x}_i x^iA120200B80201/2C90201
尺度化的目的是消除差别指标量纲的影响
假设有n个要评价的对象,m个评价指标(已经正向化了)构成的正向化矩阵如下:
X = [ x 11 x 12 ⋯ x 1 m x 21 x 22 ⋯ x 2 m ⋮ ⋮ ⋱ ⋮ x n 1 x n 2 ⋯ x n m ] X=\begin{bmatrix}x_{11}&x_{12}&\cdots&x_{1m}\\x_{21}&x_{22}&\cdots&x_{2m}\\\vdots&\vdots&\ddots&\vdots\\x_{n1}&x_{n2}&\cdots&x_{nm}\end{bmatrix} X= x11x21⋮xn1x12x22⋮xn2⋯⋯⋱⋯x1mx2m⋮xnm
那么对其尺度化后的矩阵记为Z,Z的每一个元素:
z i j = x i j ∑ i = 1 n x i j 2 z_{ij}=\frac{x_{ij}}{\sqrt{\sum_{i=1}^nx_{ij}^2}} zij=∑i=1nxij2 xij
即(每一个元素/根号下地点列元素的平方和)得到尺度化矩阵Z:
Z = [ z 11 z 12 ⋯ z 1 m z 21 z 22 ⋯ z 2 m ⋮ ⋮ ⋱ ⋮ z n 1 z n 2 ⋯ z n m ] Z=\begin{bmatrix}z_{11}&z_{12}&\cdots&z_{1m}\\z_{21}&z_{22}&\cdots&z_{2m}\\\vdots&\vdots&\ddots&\vdots\\z_{n1}&z_{n2}&\cdots&z_{nm}\end{bmatrix} Z= z11z21⋮zn1z12z22⋮zn2⋯⋯⋱⋯z1mz2m⋮znm
尺度化后,还必要给差别指标加上权重,接纳的权重确定方法有层次分析法、熵权法、Delphi法、对数最小二乘法。这里认为各个指标权重雷同。
对上述矩阵举行尺度化,得
候选人颜值牌气(争吵次数)身高体重A0.669000B0.5950.3940.9760.447C0.4460.9190.2170.894 4.3 计算得分并归一化
定义最大值:
Z + = ( m a x { z 11 , z 21 , ⋯ , z n 1 } , m a x { z 12 , z 22 , ⋯ , z n 2 } , ⋯ , m a x { z 1 m , z 2 m , ⋯ , z n m } ) Z^+=(max\{z_{11},z_{21},\cdots,z_{n1}\},max\{z_{12},z_{22},\cdots,z_{n2}\},\cdots,max\{z_{1m},z_{2m},\cdots,z_{nm}\}) Z+=(max{z11,z21,⋯,zn1},max{z12,z22,⋯,zn2},⋯,max{z1m,z2m,⋯,znm})
定义最小值:
Z − = ( m i n { z 11 , z 21 , ⋯ , z n 1 } , m i n { z 12 , z 22 , ⋯ , z n 2 } , ⋯ , m i n { z 1 m , z 2 m , ⋯ , z n m } ) Z^-=(min\{z_{11},z_{21},\cdots,z_{n1}\},min\{z_{12},z_{22},\cdots,z_{n2}\},\cdots,min\{z_{1m},z_{2m},\cdots,z_{nm}\}) Z−=(min{z11,z21,⋯,zn1},min{z12,z22,⋯,zn2},⋯,min{z1m,z2m,⋯,znm})
定义第i (i=1,2,…,n) 个评价对象与最大值的距离:
D i + = ∑ j = 1 m ( Z j + − z i j ) 2 D_i^+=\sqrt{\sum_{j=1}^m(Z_j^+-z_{ij})^2} Di+=j=1∑m(Zj+−zij)2
定义第i (i=1,2,…,n) 个评价对象与最小值的距离:
D i − = ∑ j = 1 m ( Z j − − z i j ) 2 D_i^-=\sqrt{\sum_{j=1}^m(Z_j^--z_{ij})^2} Di−=j=1∑m(Zj−−zij)2
那么,我们可以计算得出第 i( i=1,2,…,n) 个评价对象未归一化的得分:
S i = D i − D i + + D i − S_i=\frac{D_i^-}{D_i^++D_i^-} Si=Di++Di−Di−
很显着 0≤Si≤1,且 Si 越大 Di+ 越小,即越接近最大值。
我们可以将得分归一化并换成百分制:
S i ~ = S i ∑ i = 1 n S i × 100 \widetilde{S_{\mathrm{i}}}=\frac{S_{\mathrm{i}}}{\sum_{i=1}^{n}S_{\mathrm{i}}}\times100 Si =∑i=1nSiSi×100
4.4 python代码实现
import numpy as np
# 从用户输入参评数目和指标数目
print("请输入参评数目:")
n = int(input())
print("请输入指标数目:")
m = int(input())
# 接受用户输入的类型矩阵
print("请输入类型矩阵:1. 极大型 2. 极小型 3. 中间型 4.区间型")
kind = input().split(" ")
# 接受用户输入的矩阵并转化为向量
print("请输入矩阵:")
A = np.zeros(shape=(n, m))
for i in range(n):
A[i] = input().split(" ")
A[i] = list(map(float, A[i]))
print("输入矩阵为:\n{}".format(A))
# 极小型指标转化为极大型指标的函数
def minTomax(maxx, x):
x = list(x)
ans = [[(maxx-e) for e in x]]
return np.array(ans)
# 中间型指标转化为极大型指标的函数
def midTomax(bestx, x):
x = list(x)
h = [abs(e-bestx) for e in x]
M = max(h)
if M == 0:
M = 1 # 防止最大差值为0的情况
ans = [[1-(e/M) for e in h]]
return np.array(ans)
# 区间型指标转化为极大型指标的函数
def regTomax(lowx, highx, x):
x = list(x)
M = max(lowx-min(x), max(x)-highx)
if M == 0:
M = 1 # 防止最大差值为0的情况
ans = []
for i in range(len(x)):
if x[i] < lowx:
ans.append(1-(lowx-x[i])/M)
elif x[i] > highx:
ans.append(1-(x[i]-highx)/M)
else:
ans.append(1)
return np.array([ans])
# 同一指标类型,将所有指标转化为极大型指标
X = np.zeros(shape=(n, 1))
for i in range(m):
if kind[i] == "1":
v = np.array(A[:, i])
elif kind[i] == "2":
maxA = max(A[:, i])
v = minTomax(maxA, A[:, i])
elif kind[i] == "3":
print("类型三,请输入最优值:")
bestA = eval(input())
v = midTomax(bestA, A[:, i])
elif kind[i] == "4":
print("类型四,请输入区间[a,b]值a:")
lowA = eval(input())
print("类型四,请输入区间[a,b]值b:")
highA = eval(input())
v = regTomax(lowA, highA, A[:, i])
if i == 0:
X = v.reshape(-1, 1) # 如果是第一个指标,直接赋值
else:
X = np.hstack((X, v.reshape(-1, 1))) # 如果不是第一个指标,横向拼接