TOPSIS法是一种组内综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。
①基本过程为归一化后的原始数据矩阵;
②采用余弦法找出有限方案中的最优方案和最劣方案;然后分别计算各评价对象与最优方案和最劣方案间的距离;
③获得各评价对象与最优方案的相对接近程度,依次最为评价优劣的依据。
优点:该方法对数据分布及样本含量没有严格限制,数据计算简单易行。
原始数据:
共有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} & ... &x_{1m} \\ x_{21} & x_{22} & ... &x_{2m} \\ . & .& .& . \\. & .& .& . \\. & .& .& . \\x_{n1} & x_{n2} & ... &x_{nm} \end{bmatrix}
X=⎣⎢⎢⎢⎢⎢⎢⎡x11x21...xn1x12x22...xn2............x1mx2m...xnm⎦⎥⎥⎥⎥⎥⎥⎤
步骤一:首先需要进行指标属性同向化,一般选择指标正向化:
一般有以下四种指标:
1.极大型指标:期望指标值越大越好,如盈利指标,这种指标不做处理;
2.极小型指标:期望值标值越小越好,如犯错率,这种指标可以取导数,缺陷是只适用于x>0的情况;(min_to_max函数)
x
′
=
1
x
(
x
>
0
)
x'=\frac{1}{x}(x>0)
x′=x1(x>0)
一般采用最大值减去最小值,这样可以防止出现负数:
x
′
=
M
a
x
(
x
)
−
x
x'=Max(x)-x
x′=Max(x)−x
3.中间型指标:期望值标值不要过大也不要过小,而是取中间值(如水质量PH值)(mid_to_max函数,这里采取方式一:)
方式一:
x
′
=
1
−
∣
x
−
b
e
s
t
∣
m
a
x
(
∣
x
−
b
e
s
t
∣
)
x'=1-\frac{|x-best|}{max(|x-best|)}
x′=1−max(∣x−best∣)∣x−best∣
方式二:
x
′
=
{
2
×
x
−
m
i
n
(
x
)
m
a
x
(
x
)
−
m
i
n
(
x
)
,
m
≤
x
≤
m
a
x
(
x
)
+
m
i
n
(
x
)
2
2
×
m
a
x
(
x
)
−
x
m
a
x
(
x
)
−
m
i
n
(
x
)
,
m
a
x
(
x
)
+
m
i
n
(
x
)
2
≤
x
≤
m
a
x
(
x
)
x'=\left\{ \begin{aligned} 2\times\frac{x-min(x)}{max(x)-min(x)},\qquad m\le x\le \frac{max(x)+min(x)}{2}\\ 2\times\frac{max(x)-x}{max(x)-min(x)},\frac{max(x)+min(x)}{2}\le x\le max(x) \\ \end{aligned} \right.
x′=⎩⎪⎪⎪⎨⎪⎪⎪⎧2×max(x)−min(x)x−min(x),m≤x≤2max(x)+min(x)2×max(x)−min(x)max(x)−x,2max(x)+min(x)≤x≤max(x)
4.区间型指标:期望指标的取值最好落在某个区间内最好。
需要指定最优区间值的范围[a,b],最大容忍区间是[a*,b*]:
x
′
=
{
1
−
a
−
x
a
−
a
∗
,
x
<
a
1
,
a
≤
x
≤
b
1
−
x
−
b
b
∗
−
b
,
x
>
b
a
∗
=
a
−
m
i
n
(
x
)
b
∗
=
m
a
x
(
x
)
−
b
x'=\left\{ \begin{aligned} 1-\frac{a-x}{a-a*},x<a\\ 1\qquad,a\le x \le b\\ 1-\frac{x-b}{b*-b},x>b \end{aligned} \right.\\ a*=a-min(x)\\ b*=max(x)-b
x′=⎩⎪⎪⎪⎪⎨⎪⎪⎪⎪⎧1−a−a∗a−x,x<a1,a≤x≤b1−b∗−bx−b,x>ba∗=a−min(x)b∗=max(x)−b
步骤二:对数据进行标准化。(参考:三种常用数据标准化方法)
这里提供了两种方式,
方式一:归一化方法:
y
i
=
x
i
∑
i
=
1
n
x
i
y
i
∈
[
0
,
1
]
(
i
=
1
,
2
,
.
.
.
,
n
)
且
∑
i
=
1
n
y
i
=
1
y_i = \frac{x_i}{\sum_{i=1}^nx_i}\\ yi\in[0,1](i=1,2,...,n)且\sum_{i=1}^ny_i=1
yi=∑i=1nxixiyi∈[0,1](i=1,2,...,n)且i=1∑nyi=1
方式二:规范化方法:
y
i
=
x
i
−
m
i
n
(
x
)
m
a
x
(
x
)
−
m
i
n
(
x
)
y_i=\frac{x_i-min(x)}{max(x)-min(x)}
yi=max(x)−min(x)xi−min(x)
这里稍微做了一点改进,因为x_i=min(x)时,yi=0,而后面熵权法需要取对数。这里就将yi限制在[0.002,0.996]的范围内。
y
i
=
(
0.996
−
0.002
)
×
x
i
−
m
i
n
(
x
)
m
a
x
(
x
)
−
m
i
n
(
x
)
+
0.002
y_i=(0.996-0.002)\times\frac{x_i-min(x)}{max(x)-min(x)}+0.002
yi=(0.996−0.002)×max(x)−min(x)xi−min(x)+0.002
方式三:向量规范化,即每一列元素都除以当前列向量的范数(使用余弦距离度量)
y
i
=
x
i
∑
i
=
1
n
x
i
2
y_i=\frac{x_i}{\sqrt{\sum_{i=1}^nx_{i}^2}}
yi=∑i=1nxi2xi
function y = dataProcess(x,way,ind,best)
% @brief,dataProcess数据预处理函数,进行指标同向化一般选择指标正向化
% @param,way指定归一化方式分别对应方式一二三
% @param,x待处理的数据,x为n行m列的矩阵,其中行数表示样本数n,列表表示指标数m
% @param,ind为数据的处理方式,长度为m;
% ind(i)=0,表示第i个指标是极大型指标,不需要处理
% ind(i)=1,表示第i个指标是极小型指标,采用取倒数或取相反数的方式处理
% ind(i)=2,表示第i个指标是中间型指标(期望指标值既不要太大也不要太小,适当取中间值最好)
% ind(i)=3,表示第i个指标是区间型指标(期望指标的取值最好落在某一个确定的区间最好)
% @param,best为中间型或区间型指标的最佳取值范围,大小为m*2,若无则为0
[n,m] = size(x);
if nargin == 1
way = 1;
ind = zeros(m,1);
best = zeros(m,2);
elseif nargin == 2
ind = zeros(m,1);
best = zeros(m,2);
elseif nargin == 3
best = zeros(m,2);
end
%% 将数据进行正向化
for i = 1:m
if ind(i) == 1
x(:,i) = min_to_max(x(:,i));
elseif ind(i) == 2
x(:,i) = mid_to_max(x(:,i),best(i,1));
elseif ind(i) == 3
x(:,i) = sec_to_max(x(:,i),best(i,1),best(i,2));
end
end
%% 将数据进行标准化
if way == 1
%---------------- 方式一:一般归一化方法 ----------------
y = x ./ repmat(sum(x),n,1);
% 这种写法等价于
% for i=1:n
% for j=1:m
% p(i,j)=y(i,j)/sum(y(:,j));
% end
% end
%---------------- 方式二:为了避免0的出现,归一化到某一范围内 ----------------
elseif way == 2
% 求每一行的最大值
xMax = max(x);
% 求每一行的最小值
xMin = min(x);
% 不归一化到[0,1]范围内,因为0不能求对数,这里取[0.002,0.996]
helperMax = 0.996;
helperMin = 0.002;
helper = helperMax - helperMin;
y = zeros(size(x));
for i = 1:m
temp = xMax(i) - xMin(i);
y(:,i) = helper*(x(:,i)-xMin(i))/temp + helperMin;
end
%---------------- 方式三:向量规范化,即每一列元素都除以当前列向量的范数----------------
elseif way == 3
y = x ./ repmat(sqrt(sum(x.*x)), n, 1); % 一般标准化
end
return;
end
function [y] = min_to_max(x)
% 极小型指标:期望指标值越小越好(如患病率、死亡率等)
% 可以化成y=1/x(x>0)或y=max(x)-x
y = max(x) - x;
return;
end
function [y] = mid_to_max(x,best)
% 中间型指标:期望指标值既不要太大也不要太小,适当取中间值最好(如水质量评估PH值)
M = max(abs(x-best));
y = 1 - abs(x-best) / M;
% 也可以写成
% Xmin = min(x);
% Xmax = max(x);
% Xmid = (Xmin+Xmax)/2;
% Xdiv = Xmax - Xmin;
% if x>=Xmin && x <= Xmid
% y = 2*(x-Xmin)/Xdiv;
% else
% y = 2*(Xmax-x)/Xdiv;
% end
end
function [y] = sec_to_max(x,min_n,max_n)
% 区间型指标:期望指标的取值最好落在某一个确定的区间最好(如体温)
% [min_n,max_n]为指标x的最佳稳定区间
n = size(x,1); % 行数,即为对象个数
M = max([min_n-min(x),max(x)-max_n]); % 最大容忍区间
y = zeros(n,1);
for i = 1: n
if x(i) < min_n
y(i) = 1-(min_n-x(i))/M;
elseif x(i) > max_n
y(i) = 1-(x(i)-max_n)/M;
else
y(i) = 1;
end
end
end
步骤二:采用熵权法处理数据。
1.因为这里已经对数据进行了标准化处理,设标准化处理后的数据为y,因此不要再处理;
2.计算各指标的熵值:(n为样本数,m为指标数)
e
j
=
−
1
l
n
(
n
)
∑
i
=
1
n
y
i
j
l
n
(
y
i
j
)
(
j
=
1
,
2
,
.
.
.
,
m
)
e_j=-\frac{1}{ln(n)}\sum_{i=1}^ny_{ij}ln(y_{ij})(j=1,2,...,m)
ej=−ln(n)1i=1∑nyijln(yij)(j=1,2,...,m)
3.计算信息效用值:信息效用值越大,表示该指标越重要。
d
j
=
1
−
e
j
d_j=1-e_j
dj=1−ej
4.计算各指标的权系数:熵权系数dj越大,代表指标代表的信息量越大,表示其对综合评价的作用越大。
W
j
=
d
j
∑
j
=
1
n
d
j
W_j=\frac{d_j}{\sum_{j=1}^nd_j}
Wj=∑j=1ndjdj
function [score, weight] = entropyWeight(x)
% 使用熵权法求数据行的得分及各指标(列)的权重
% x为原始数据矩阵, 一行代表一个样本, 每列对应一个指标
% ind指示向量,指示各列正向指标还是负向指标,1表示正向指标,2表示负向指标
% score返回各行(样本)得分,weight返回各列权重
[n,m] = size(x);
% 计算每个指标的熵值
k = 1/log(n);
e = zeros(1,m);
lnx = Myln(x);
for j = 1:m
e(j) = -k * sum(x(:,j).*lnx(:,j));
end
% 计算熵冗余度
d = ones(1,m) - e;
% 计算权值
weight = d/sum(d);
% 计算综合得分
score = 100 * weight * x';
这里进行了补充定义:(见Myln函数)
当
y
i
j
=
0
时
l
n
(
y
i
j
)
=
0
当y_{ij}=0时ln(y_{ij})=0
当yij=0时ln(yij)=0
function lnx = Myln(x)
% 方法一和方法二都可能会出现y=0的情况需要特别对出现0的情况进行处理
lnx = zeros(size(x));
lnx(x==0) = 0;
lnx(x~=0) = log(x(x~=0));
end
步骤三:
采用TOPSIS方法:
1.首先需要对属性向量规范化,即每一列元素都除以当前列向量的范数(使用余弦距离度量),即前面所述规范化的方式三,将规范化后的矩阵即为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} & ... &z_{1m} \\ z_{21} & z_{22} & ... &z_{2m} \\ . & .& .& . \\. & .& .& . \\. & .& .& . \\z_{n1} & z_{n2} & ... &z_{nm} \end{bmatrix}
Z=⎣⎢⎢⎢⎢⎢⎢⎡z11z21...zn1z12z22...zn2............z1mz2m...znm⎦⎥⎥⎥⎥⎥⎥⎤
2.确定最优方案和最劣方案:
最优方案由每个Z中每个方案的最大值构成:
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
n
,
z
2
n
,
.
.
.
,
z
n
m
}
)
=
(
Z
1
+
,
Z
2
+
,
.
.
.
,
Z
m
+
)
Z^+=(max\{z_{11},z_{21},...,z_{n1}\},max\{z_{12},z_{22},...,z_{n2}\},... max\{z_{1n},z_{2n},...,z_{nm}\}) \\=(Z_1^+,Z_2^+,...,Z_m^+)\qquad\qquad\qquad\qquad\qquad\qquad\quad
Z+=(max{z11,z21,...,zn1},max{z12,z22,...,zn2},...max{z1n,z2n,...,znm})=(Z1+,Z2+,...,Zm+)
最劣方案由每个Z中每个方案的最小值构成:
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
n
,
z
2
n
,
.
.
.
,
z
n
m
}
)
=
(
Z
1
−
,
Z
2
−
,
.
.
.
,
Z
m
−
)
Z^-=(min\{z_{11},z_{21},...,z_{n1}\},min\{z_{12},z_{22},...,z_{n2}\},... min\{z_{1n},z_{2n},...,z_{nm}\}) \\=(Z_1^-,Z_2^-,...,Z_m^-)\qquad\qquad\qquad\qquad\qquad\qquad\quad
Z−=(min{z11,z21,...,zn1},min{z12,z22,...,zn2},...min{z1n,z2n,...,znm})=(Z1−,Z2−,...,Zm−)
3.计算各评价对象与最优方案、最劣方案的接近程度,这里的w取得即是通过熵权法计算出来的权重。
D
i
+
=
∑
j
=
1
m
w
j
(
Z
j
+
−
z
i
j
)
2
D
i
−
=
∑
j
=
1
m
w
j
(
Z
j
−
−
z
i
j
)
2
D_i^+=\sqrt{\sum_{j=1}^mw_j(Z_j^+-z_{ij})^2}\qquad D_i^-=\sqrt{\sum_{j=1}^mw_j(Z_j^--z_{ij})^2}
Di+=j=1∑mwj(Zj+−zij)2Di−=j=1∑mwj(Zj−−zij)2
4.计算各评价对象与最优方案的贴近程度Ci
C
i
=
D
i
−
D
i
+
+
D
i
−
C_i=\frac{D_i^-}{D_i^+ + D_i^-}
Ci=Di++Di−Di−
0
≤
C
i
≤
1
,
C
i
→
1
,
表
明
评
价
对
象
越
优
。
0\le C_i\le1,C_i\rightarrow1,表明评价对象越优。
0≤Ci≤1,Ci→1,表明评价对象越优。
function [sorted_S,index] = topsis(x,weights)
% 求解TOPSIS算法
% X={x1,x2,..,xn},原始数据集,这里取归一化之后的数据,有m个指标;有n个样本
% weights={w1,w2,...wn},各指标权重;
[n,m] = size(x);
%% 计算各平均对象与最优方案、最劣方案的接近程度
yMax = max(x);
yMin = min(x);
DMax = zeros(n,1);
DMin = zeros(n,1);
Score = zeros(n,1);
for i = 1:n
for j = 1:m
DMax(i) = DMax(i) + weights(j)*(yMax(j)-x(i,j))^2;
DMin(i) = DMin(i) + weights(j)*(yMin(j)-x(i,j))^2;
end
Score(i) = DMin(i) / (DMax(i) + DMin(i));
end
%% 计算各评价对象与最优方案的贴近程度
% 其中0<=C<=1,C越接近与1,说明评价对象越优
StandScore = Score / sum(Score);
%% 根据C的大小进行排序,得出评价结果
[sorted_S,index] = sort(StandScore ,'descend');
最后一步主函数写法:
clc;
clear;
%% 第一步:导入数据
load data_water_quality.mat
%% 第二步:熵权法计算,采用一般归一化方法
p=dataProcess(X,1,[1,2,3,1],[0,0;5,0;30,40;0,0]);
[score, weight] = entropyWeight(p);
%% 第三步:TOPSIS法计算,采用向量规范化
X = dataProcess(X,3,[1,2,3,1],[0,0;5,0;30,40;0,0]);
[sorted_S,index] = topsis(X,weight)
主要参考:
TOPSIS法(优劣解距离法)介绍及 python3 实现
有错误的话,欢迎指出!