IMMC2020:熵权TOPSIS
笔记整理来自清风老师的数学建模课程:TOPSIS教程
目录
1. 层次分析法的局限性(主观求权重方法)
2. TOPSIS法引入
2.1 一个指标的情况
2.2 2个指标的情况
2.2.1 指标正向化
2.2.2 指标标准化处理
2.2.3 计算得分
2.2.4 实例计算
3. TOPSIS简介
4. TOPSIS法步骤
4.1 将原始矩阵正向化(可以在Excel中完成)
4.1.1 极小型指标转换为极大型指标
4.1.2 中间型指标转换为极大型指标
4.1.3 区间型指标转换为极大型指标
4.2 正向化矩阵标准化
4.3 计算得分并归一化
5. 例题:评价水质情况
6. 代码讲解
6.1 将数据导入到MATLAB中
6.2 判断指标是否正向化
6.2.1 极小型指标正向化
6.2.3 中间型指标正向化
6.2.4 区间型指标正向化
6.2.5 指标正向化处理
6.3 对正向化后的矩阵进行标准化
6.4 计算得分并归一化(计算与最大值的距离和最小值的距离,并算出得分)
7. 模型拓展
层次分析法真正的核心是判断矩阵的填写,但是判断矩阵受人为因素比较大,所以最后计算得出的权重也比较主观。如果在有数据的情况下最好不要使用层次分析法。
(1)评价的决策层不能太多,太多的话n会很大,判断矩阵和一致性差异可能会很大。(可能会通过不了一致性检验)
(2)如果决策层中指标的数据是已知的,那么我们如何利用这些数据来使得评价更加准确呢?
可以分析数据内在的特征就行评价。(熵权法、TOPSIS法)
小明同宿舍共有四名同学,他们第一学期的高数成绩如下表所示:
请你为这四名同学进行评分,该评分能合理的描述其高数成绩的高低。
(注:这里要求的评分可以类比于上一讲层次分析法中要求的那个权重)
修正后的排名表示数字越大越好,评分用排名的得分/总得分
可以随便修改成绩,只要保证排名不变,那么评分就不会改变!
【矛盾】评分没变说明结果有问题,说明这种评分方式不能够全部反应原始数据的全部信息。
想法1:把数都减去一个最小值。结果通过与(max-min)相处,将数字变为【0,1】之间的数。
将数归一化:
需要说明的问题:如果用下面这种方法,虽然结果更加精确,能够反应更多的原始信息;比如60分时,我们得到的结果是0.6,而不是0。但是需要知道理论的最大值和最小值。
但是大多数情况下,我们是无法知道理论的最大值与最小值的,只能得到1组数据中的最大值与最小值,所以常用的评分方法是上一种。
为什么不用上面表格这个理论最大值最小值的公式:
新增加了一个指标,现在要综合评价四位同学,并为他们进行评分。
成绩是越高(大)越好,这样的指标称为极大型指标(效益型指标)。
与他人争吵的次数越少(越小)越好,这样的指标称为极小型指标(成本型指标)。
在进行分析的时候我们需要将指标统一为一个类型,一般都转为极大型指标。
将所有的指标转化为极大型称为指标正向化(最常用)
可以在excel中进行计算。比如折扣需要正向化处理。
只有一个指标的时候不需要消除量纲的影响,但是2个指标及以上呢?
由于成绩和争吵次数的量纲不同(单位不同),所以需要消除指标对不同量纲的影响。
为了消去不同指标量纲的影响,需要对已经正向化的矩阵进行标准化处理。
可以发现标准化后不会影响到指标的相对大小。
matlab代码:B = repmat(A,m,n):将矩阵A复制m×n块,即把A作为B的元素,B由m×n个A平铺而成。
X = [89 1; 60 3; 74 2; 99 0]
[n,m] = size(X)
X./repmat(sum(X.*X).^0.5,n,1)
代码分解:
X.*X
sum(X.*X)
sum(X.*X).^0.5
由于矩阵(点除)除法的运算需要行列一致。
repmat(sum(X.*X).^0.5,n,1)
X./repmat(sum(X.*X).^0.5,n,1)
所以:
计算多个指标的得分时,可以类别只有一个指标时的得分。
先求出每一列的最大值最小值,再求每个元素与最大值(最小值)的距离(欧式距离)。最后求得分即可。(和只有一个指标时的解法一样)
代码:
X = [89,1; 60,3; 74,2;99,0]%已经正向化后的矩阵
[n,m] = size(X)
Z = X./repmat(sum(X.*X) .^ 0.5,n,1)%标准化
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5; % D+ 与最大值的距离向量
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ],2) .^ 0.5; % D- 与最小值的距离向量
S = D_N ./ (D_P+D_N); % 未归一化的得分
D+代码分解:D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5; % D+ 与最大值的距离向量
max(Z)%求出Z矩阵中每列的最大值。
repmat(max(Z),n,1)%将max(Z)矩阵复制n次
(Z - repmat(max(Z),n,1))%得到每一行的数与最大值的差
(Z - repmat(max(Z),n,1)) .^ 2%得到每行中的每个数与其最大值差的平方
sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2)%得到(Z - repmat(max(Z),n,1)) .^ 2 ]矩阵每一行的和 后面不加2默认是求每一列的和。
sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5 %将 sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) 的结果开根号
最后求得的结果就是D+的结果。
结果如下:
C.L.Hwang 和 K.Yoon 于1981年首次提出 TOPSIS (Technique for Order Preference by Similarity to an Ideal Solution),可翻译为逼近理想解排序法,国内常简称为优劣解距离法。
TOPSIS 法是一种常用的综合评价方法,能充分利用原始数据的信息,其结果能精确地反映各评价方案之间的差距。
基本过程为:(1)将原始数据矩阵统一指标类型(一般正向化处理)得到正向化的矩阵;
(2)再对正向化的矩阵进行标准化处理以消除各指标量纲的影响;
(3)并找到有限方案中的最优方案和最劣方案;
(4)然后分别计算各评价对象与最优方案和最劣方案间的距离;
(5)获得各评价对象与最优方案的相对接近程度,以此作为评价优劣的依据。
该方法对数据分布及样本含量没有严格限制,数据计算简单易行。
化简后的结果尽量在[0,1]之间。并且越靠近于最优值(这里为7)越接近于1.
标准化的目的是消除不同指标量纲的影响
代码知识点:
(1)将EXCEL中的数据导入到Matlab,并另存为mat文件,下次可直接load Matlab中函数的编写和调用
(2)magic(n)幻方矩阵
(3)sort函数
(4)zeros和ones函数
第一步:Ctrl+C复制Excel中的数据
第二步:在工作区新建一个空白的数据文件(.mat),命名为data_water.
第三步:双击data_water,将数据按住Ctrl+v粘贴到里面即可。
第四步:右击数据文件,另存为.mat文件,下次使用时可以直接用load导入数据。
代码:
load data_water.mat
然后可以将数据表的文件名改成X(短一些,好写代码)
第一步:判断是否需要正向化,只有当存在非极大型指标时才需要正向化处理。
[n,m] = size(X);
disp(['共有' num2str(n) '个评价对象, ' num2str(m) '个评价指标'])
Judge = input(['这' num2str(m) '个指标是否需要经过正向化处理,需要请输入1 ,不需要输入0: ']);
这里采用矩阵的形式拼接字符。
第二步:如果需要正向化处理,输入1.
if Judge == 1
Position = input('请输入需要正向化处理的指标所在的列,例如第2、3、6三列需要处理,那么你需要输入[2,3,6]: '); %[2,3,6]
disp('请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型) ')
Type = input('例如:第2列是极小型,第3列是区间型,第6列是中间型,就输入[1,3,2]: '); %[2,1,3]
% 注意,Position和Type是两个同维度的行向量
for i = 1 : size(Position,2) %这里需要对这些列分别处理,因此我们需要知道一共要处理的次数,即循环的次数
X(:,Position(i)) = Positivization(X(:,Position(i)),Type(i),Position(i));
% Positivization是我们自己定义的函数,其作用是进行正向化,其一共接收三个参数
% 第一个参数是要正向化处理的那一列向量 X(:,Position(i)) 回顾上一讲的知识,X(:,n)表示取第n列的全部元素
% 第二个参数是对应的这一列的指标类型(1:极小型, 2:中间型, 3:区间型)
% 第三个参数是告诉函数我们正在处理的是原始矩阵中的哪一列
% 该函数有一个返回值,它返回正向化之后的指标,我们可以将其直接赋值给我们原始要处理的那一列向量
end
disp('正向化后的矩阵 X = ')
disp(X)
end
可以得到正向化后的矩阵为:
4.69 | 0.717241379 | 3 | 1 |
2.03 | 0.406896552 | 35 | 0.694036301 |
9.11 | 0.524137931 | 8 | 0.905790838 |
8.61 | 0.965517241 | 8 | 0.444252377 |
7.13 | 0.655172414 | 4 | 0.691443388 |
2.39 | 0.84137931 | 16 | 0.600691443 |
7.69 | 0.855172414 | 16 | 0.65514261 |
9.3 | 0.868965517 | 27 | 0 |
5.45 | 0.572413793 | 49 | 1 |
6.19 | 0.813793103 | 37 | 0.784788245 |
7.93 | 0.634482759 | 45 | 0.699222126 |
4.4 | 0.806896552 | 37 | 0.541918755 |
7.46 | 0.144827586 | 31 | 1 |
2.01 | 0 | 7 | 0.454624028 |
2.04 | 0.586206897 | 31 | 1 |
7.73 | 0.406896552 | 2 | 1 |
6.35 | 0.6 | 29 | 0.182368194 |
8.29 | 0.027586207 | 15 | 1 |
3.54 | 0.813793103 | 0 | 0.408815903 |
7.44 | 0.489655172 | 46 | 0.273120138 |
function [posit_x] = Min2Max(x)
posit_x = max(x) - x;
%posit_x = 1 ./ x; %如果x全部都大于0,也可以这样正向化
end
function [posit_x] = Mid2Max(x,best)
M = max(abs(x-best));
posit_x = 1 - abs(x-best) / M;
end
function [posit_x] = Inter2Max(x,a,b)
r_x = size(x,1); % row of x
M = max([a-min(x),max(x)-b]);
posit_x = zeros(r_x,1); %zeros函数用法: zeros(3) zeros(3,1) ones(3)
% 初始化posit_x全为0 初始化的目的是节省处理时间
for i = 1: r_x
if x(i) < a
posit_x(i) = 1-(a-x(i))/M;
elseif x(i) > b
posit_x(i) = 1-(x(i)-b)/M;
else
posit_x(i) = 1;
end
end
end
% function [输出变量] = 函数名称(输入变量)
% 函数的中间部分都是函数体
% 函数的最后要用end结尾
% 输出变量和输入变量可以有多个,用逗号隔开
% function [a,b,c]=test(d,e,f)
% a=d+e;
% b=e+f;
% c=f+d;
% end
% 自定义的函数要单独放在一个m文件中,不可以直接放在主函数里面(和其他大多数语言不同)
function [posit_x] = Positivization(x,type,i)
% 输入变量有三个:
% x:需要正向化处理的指标对应的原始列向量
% type: 指标的类型(1:极小型, 2:中间型, 3:区间型)
% i: 正在处理的是原始矩阵中的哪一列
% 输出变量posit_x表示:正向化后的列向量
if type == 1 %极小型
disp(['第' num2str(i) '列是极小型,正在正向化'] )
posit_x = Min2Max(x); %调用Min2Max函数来正向化
disp(['第' num2str(i) '列极小型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 2 %中间型
disp(['第' num2str(i) '列是中间型'] )
best = input('请输入最佳的那一个值: ');
posit_x = Mid2Max(x,best);
disp(['第' num2str(i) '列中间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
elseif type == 3 %区间型
disp(['第' num2str(i) '列是区间型'] )
a = input('请输入区间的下界: ');
b = input('请输入区间的上界: ');
posit_x = Inter2Max(x,a,b);
disp(['第' num2str(i) '列区间型正向化处理完成'] )
disp('~~~~~~~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~~~~~~')
else
disp('没有这种类型的指标,请检查Type向量中是否有除了1、2、3之外的其他值')
end
end
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);
disp('标准化矩阵 Z = ')
disp(Z)
可以得到标准化后的矩阵为:
0.162185916 | 0.248255278 | 0.024544035 | 0.306457563 |
0.070199874 | 0.140837129 | 0.286347071 | 0.212692674 |
0.315034904 | 0.181417319 | 0.065450759 | 0.277586453 |
0.297744294 | 0.334189798 | 0.065450759 | 0.136144501 |
0.24656409 | 0.226771648 | 0.03272538 | 0.211898056 |
0.082649113 | 0.291222538 | 0.130901518 | 0.184086436 |
0.265929573 | 0.295996678 | 0.130901518 | 0.200773408 |
0.321605335 | 0.300770818 | 0.220896312 | 0 |
0.188467643 | 0.198126809 | 0.4008859 | 0.306457563 |
0.214057745 | 0.281674258 | 0.302709761 | 0.240504293 |
0.274229065 | 0.219610438 | 0.36816052 | 0.214281909 |
0.152157363 | 0.279287188 | 0.302709761 | 0.166075101 |
0.257975892 | 0.05012847 | 0.253621692 | 0.306457563 |
0.06950825 | 0 | 0.057269414 | 0.139322972 |
0.070545686 | 0.202900949 | 0.253621692 | 0.306457563 |
0.267312822 | 0.140837129 | 0.01636269 | 0.306457563 |
0.21959074 | 0.207675088 | 0.237259002 | 0.055888112 |
0.286678304 | 0.00954828 | 0.122720173 | 0.306457563 |
0.122417515 | 0.281674258 | 0 | 0.125284726 |
0.257284268 | 0.169481969 | 0.376341865 | 0.083699732 |
D_P = sum([(Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5; % D+ 与最大值的距离向量
D_N = sum([(Z - repmat(min(Z),n,1)) .^ 2 ],2) .^ 0.5; % D- 与最小值的距离向量
S = D_N ./ (D_P+D_N); % 未归一化的得分
disp('最后的得分为:')
stand_S = S / sum(S)%归一化后的得分
%[sorted_S,index] = sort(stand_S ,'descend')
排序(可以在Excel中完成),可以看出河流K的得分最高,排名最高。
河流 | D+ | D- | Stand_S(归一化后得分) | 排名 |
K | 0.1579 | 0.5212 | 0.0702 | 1 |
J | 0.1683 | 0.4997 | 0.0684 | 2 |
I | 0.1904 | 0.5550 | 0.0681 | 3 |
L | 0.2471 | 0.4517 | 0.0591 | 4 |
T | 0.2855 | 0.4611 | 0.0565 | 5 |
G | 0.2977 | 0.4285 | 0.0539 | 6 |
O | 0.3193 | 0.4466 | 0.0533 | 7 |
M | 0.3262 | 0.4430 | 0.0527 | 8 |
H | 0.3570 | 0.4503 | 0.0510 | 9 |
D | 0.3770 | 0.4320 | 0.0488 | 10 |
C | 0.3698 | 0.4178 | 0.0485 | 11 |
B | 0.3500 | 0.3835 | 0.0478 | 12 |
Q | 0.3405 | 0.3537 | 0.0466 | 13 |
A | 0.4177 | 0.4059 | 0.0451 | 14 |
F | 0.3832 | 0.3688 | 0.0448 | 15 |
R | 0.4289 | 0.3953 | 0.0438 | 16 |
P | 0.4338 | 0.3913 | 0.0434 | 17 |
E | 0.4021 | 0.3588 | 0.0431 | 18 |
S | 0.4858 | 0.3128 | 0.0358 | 19 |
N | 0.5668 | 0.1506 | 0.0192 | 20 |