优劣解距离法(Topsis)
平时,我们常见的评价方法有:
- 动态加权综合评价
- Topsis优劣解距离评价法
- 模糊综合评价
- 层次分析法
- 灰色关联分析用于综合评价
今天我就来介绍一下Topsis优劣解距离评价法。
1. 概念
TOPSIS法(Technique for Order Preference by Similarity to ldeal Solution),简称为优劣解距离法,是一种常用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。
2. 原理
讲原理的过程中,我们举个例子会更好理解一些,比如某学校将进行老师综合素质评价,现有如下指标,计算哪个老师综合素质最高:
姓名 | 教学评分 | 请假次数 |
张三 | 88 | 3 |
李四 | 79 | 1 |
王五 | 90 | 0 |
彭六 | 93 | 5 |
1. 原始矩阵正向化
平常常见的指标有:
指标名称 | 指标特点 | 例子 |
极大型(效益型)指标 | 越大(多)越好 | 成绩、GDP增速、企业利润 |
极小型(成本型)指标 | 越小(少)越好 | 费用、坏品率、污染程度 |
中间型指标 | 越接近某个值越好 | 水质量评估时的PH值 |
区间型指标 | 落在某个区间最好 | 体温、水中植物性营养物量 |
原始矩阵正向化,即将所有的指标类型统一转化为
极大型指标,但转化方法可以不同!
-
极小型指标→极大型指标: m a x − x max-x max−x
-
中间型指标→极大型指标:
{ x i } \lbrace x_i \rbrace {xi}是一组中间型指标序列,且最佳的数值为 x b e s t x_{best} xbest,则正向化公式为:
M = m a x { ∣ x i − x b e s t ∣ } M=max{\lbrace| x_i-x_{best}| \rbrace} M=max{∣xi−xbest∣}
x i = 1 − ∣ x i − x b e s t ∣ M x_i = 1-{| x_i-x_{best}| \over M} xi=1−M∣xi−xbest∣
比如:
一组PH值PH值 5 7 6 8 9 x b e s t = 7 , M = m a x { ∣ 5 − 7 ∣ } x_{best}=7,M=max{\lbrace| 5-7| \rbrace} xbest=7,M=max{∣5−7∣}
-
区间型指标→极大型指标
{ x i } \lbrace x_i \rbrace {xi}是一组中间型指标序列,且最佳的区间为[a,b],则正向化公式为:
x ~ = { 1 − a − x M , x < a 1 , a ≤ x ≤ b 1 − x − b M , x > b \widetilde{x}= \left\{ \begin{aligned} 1-{a-x\over M}, x<a \\ 1 , a \leq x \leq b\\ 1-{x-b\over M}, x>b \end{aligned} \right. x =⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧1−Ma−x,x<a1,a≤x≤b1−Mx−b,x>b
其中, M = m a x { a − m i n { x i } , m a x { x i } − b } M=max\{a-min\{x_i\}, max\{x_i\}-b\} M=max{a−min{xi},max{xi}−b}
正向化后的矩阵为:
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 =\left[ \begin{matrix} X_{11} & X_{12} & ... & X_{1m}\\ X_{21} & X_{22} & ... & X_{2m}\\ ... & ... & ... & ...\\ X_{n1} & X_{n2} & ... & X_{nm}\\ \end{matrix} \right]
X=⎣⎢⎢⎡X11X21...Xn1X12X22...Xn2............X1mX2m...Xnm⎦⎥⎥⎤
2. 正向化矩阵标准化
将上一步得到的正向化矩阵进行标准化,标准化的矩阵记为Z,Z中的每一个元素:
Z
i
j
=
x
i
j
∑
i
=
1
n
x
i
j
2
Z_{ij} = {x_{ij} \over \sqrt{\sum\limits_{i=1}^n{x_{ij}^2}}}
Zij=i=1∑nxij2xij
即
每
一
个
元
素
其
所
在
列
的
元
素
的
平
方
和
每一个元素\over \sqrt{其所在列的元素的平方和}
其所在列的元素的平方和每一个元素
得到标准化矩阵:
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 =\left[ \begin{matrix} Z_{11} & Z_{12} & ... & Z_{1m}\\ Z_{21} & Z_{22} & ... & Z_{2m}\\ ... & ... & ... & ...\\ Z_{n1} & Z_{n2} & ... & Z_{nm}\\ \end{matrix} \right]
Z=⎣⎢⎢⎡Z11Z21...Zn1Z12Z22...Zn2............Z1mZ2m...Znm⎦⎥⎥⎤
3. 计算得分并归一化
定义最大值:
Z
+
=
(
Z
1
+
,
Z
2
+
,
.
.
.
,
Z
m
+
)
Z^+=(Z^+_1, Z^+_2, ..., Z^+_m)
Z+=(Z1+,Z2+,...,Zm+)
最小值
Z
−
=
(
Z
1
−
,
Z
2
−
,
.
.
.
,
Z
m
−
)
Z^-=(Z^-_1, Z^-_2, ..., Z^-_m)
Z−=(Z1−,Z2−,...,Zm−)
第i个评价对象与最大值距离为:
D
i
+
=
∑
j
=
1
m
(
Z
j
+
−
z
i
j
)
2
D_i^+= \sqrt{\sum\limits_{j=1}^m(Z_j^+-z_{ij})^2}
Di+=j=1∑m(Zj+−zij)2
第i个评价对象与最小值距离为:
D
i
−
=
∑
j
=
1
m
(
Z
j
−
−
z
i
j
)
2
i
=
1
,
2
,
.
.
.
,
n
D_i^-= \sqrt{\sum\limits_{j=1}^m(Z_j^--z_{ij})^2} \quad i=1,2,...,n
Di−=j=1∑m(Zj−−zij)2i=1,2,...,n
可以计算得到,第i个评价对象未归一化得分为:
S
i
=
D
i
−
D
i
−
+
D
i
+
S_i = {D_i^- \over {D_i^-+D_i^+}}
Si=Di−+Di+Di−
最后归一化:
S
i
′
=
S
i
−
S
m
i
n
S
m
a
x
−
S
m
i
n
S_i ^{'} = {S_i - S_{min} \over {S_{max} - S_{min}}}
Si′=Smax−SminSi−Smin
最后得到的 S i ′ S_i ^{'} Si′就是需要的得分!
3. 代码实现
# TOPSIS计算公司发展水平
class TOPSIS:
# 初始化
def __init__(self, df, feature_list):
self.df = df # 输入dataframe,这份用来下面算法操作
self.df_copy = df.copy() # 备份,因为操作的时候回改变原始数据,所以这份数据用来储存计算结果
self.feature_list = feature_list # 要作为评价特征的特征
self.features_num = len(feature_list) # 特征个数
self.features_length = df.shape[0] # 样本数量
# 标准化
def standardization(self):
for f in self.feature_list:
self.df[f] = self.df[f] / np.sqrt(sum(np.power(self.df[f], 2)))
# 计算D+, D-
def D_calculation(self):
self.standardization()
self.df_copy['D+'] = 0
self.df_copy['D-'] = 0
for i in range(self.features_length):
self.df_copy['D+'].iloc[i] = np.sqrt(sum([(self.df[feature].iloc[i]-np.max(self.df[feature]))**2 for feature in self.feature_list]))
self.df_copy['D-'].iloc[i] = np.sqrt(sum([(self.df[feature].iloc[i]-np.min(self.df[feature]))**2 for feature in self.feature_list]))
return self.df
# 计算未归一化得分
def non_normalized_score(self):
self.D_calculation()
self.df_copy['score_unnormalized'] = self.df_copy['D-'] / (self.df_copy['D+'] + self.df_copy['D-'])
# 计算归一化得分
def normalized_score(self):
self.non_normalized_score()
self.df_copy['score_normalized'] = (self.df_copy['score_unnormalized'] - min(self.df_copy['score_unnormalized'])) \
/ (max(self.df_copy['score_unnormalized'])-min(self.df_copy['score_unnormalized']))
return self.df_copy
代码实操:
我随机编撰了一段数据,通过TOPSIS来计算数据中公司的发展情况,v1、v2、v3指的是能代表该公司发展状况的特征:
# 计算
data = pd.read_excel(r'.\topsis_test.xlsx')
features = ['v1', 'v2', 'v3']
data = TOPSIS(data, features).normalized_score()
data
得到结果为:
可以看到计算结果中有距离结果、也有未归一化、归一化得分。
从归一化得分可以看出company1发展情况最好!