TOPSIS和熵权法的应用(Matlab实现,包括数据预处理)

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=1max(xbest)xbest
方式二:
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)xmin(x),mx2max(x)+min(x)2×max(x)min(x)max(x)x,2max(x)+min(x)xmax(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*},xb \end{aligned} \right.\\ a*=a-min(x)\\ b*=max(x)-b x=1aaax,x<a1,axb1bbxb,x>ba=amin(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=1nyi=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)ximin(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.9960.002)×max(x)min(x)ximin(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=1nxi2 xi

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=1nyijln(yij)(j=1,2,...,m)
3.计算信息效用值:信息效用值越大,表示该指标越重要。
d j = 1 − e j d_j=1-e_j dj=1ej
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=0ln(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=1mwj(Zj+zij)2 Di=j=1mwj(Zjzij)2
4.计算各评价对象与最优方案的贴近程度Ci
C i = D i − D i + + D i − C_i=\frac{D_i^-}{D_i^+ + D_i^-} Ci=Di++DiDi
0 ≤ C i ≤ 1 , C i → 1 , 表 明 评 价 对 象 越 优 。 0\le C_i\le1,C_i\rightarrow1,表明评价对象越优。 0Ci1,Ci1

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 实现

有错误的话,欢迎指出!

你可能感兴趣的:(matlab,matlab,数学建模)