提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
文章目录
前言
通过模型算法,熟练对Matlab和python的应用。
学习视频链接:
https://www.bilibili.com/video/BV1EK41187QF?p=4&vd_source=67471d3a1b4f517b7a7964093e62f7e6
一、TOPSIS法
1.模型原理
TOPSIS法是一种理想目标相似性的顺序选优技术,在多目标决策分析中是一种非常有效的方法。它通过归一化后(去量纲化)的数据规范化矩阵,找出多个目标中最优目标和最劣目标(分别用理想解和反理想解表示),分别计算各评价目标与理想解和反理想解的距离,获得各目标与理想解的贴近度,按理想解贴近度的大小排序,以此作为评价目标优劣的依据。贴近度取值在0~1之间,该值愈接近1,表示相应的评价目标越接近最优水平;反之,该值愈接近0,表示评价目标越接近最劣水平。(我的理解是,在 n 维空间中,各评价目标与理想解的距离;距离越近,越优。)
TOPSIS法的优点在于其计算过程简单明了,能够较好地处理多个评价指标,且考虑了各指标的权重及其对决策的影响。该方法被广泛应用于各种决策分析场景,如供应商选择、项目评估和绩效考核等。
2.基本步骤
(1)将原始矩阵正向化
将原始矩阵正向化,就是要将所有的指标类型统一转化为极大型指标。
(2)正向矩阵标准化
标准化的方法有很多种,其主要目的就是去除量纲的影响,保证不同评价指标在同一数量级,且数据大小排序不变。
(3)计算得分并归一化
(1)原始矩阵正向化
将所有的指标类型统一转化为极大型指标(极大型指标就是,越接近理想值,值越大)。
各类型指标的转化公式:
视频中江北老师举了找对象的例子:
对颜值、脾气、身高、体重四个指标进行考察。其中颜值是极大型指标,脾气(争吵次数)是极小型指标;身高是中间型指标,对相亲对象身高要求在165cm;体重是区间型指标,对相亲对象体重要求在90-100(斤)之间。
(2)正向矩阵标准化
正向矩阵标准化的目的是消除不同指标量纲的影响。
注:在标准化后一般要考虑权重,在本实例中认为各个指标的权重相同。
(3)计算得分并归一化
得到标准化矩阵Z后,定义最大值和最小值。
最大值为 Z 的每一列最大值组成的行向量。
最小值为 Z 的每一列最小值组成的行向量。
定义第 i (i = 1,2,…,n)个评价对象与最大值的距离:
定义第 i (i = 1,2,…,n)个评价对象与最小值的距离:
接下来我们计算得出第 i (i = 1,2,…,n)个评价对象未归一化的得分:
显然可得:Si 在 0 到 1 之间,且 Si 越大 Di+ 越小,即越接近最大值。
二、代码实现----Matlab
在本实例中,对不同指标有不同的处理公式,所以在代码中加入了函数,对不同指标调用不同函数进行处理。
Matlab中,对函数的定义:
% function[输出变量] = 函数名称(输入变量)
% 函数的中间部分都是函数体
% 函数的最后要用end结尾
% 输出变量和输入变量可以有多个,用逗号隔开
% function[a,b,c] = test(d,e,f)
% a = d + e;
% b = e + f;
% c = f + d;
% end
1.主程序
clear;clc
% 1.判断是否需要正向化
% A = [9, 10, 175, 120; 8, 7, 164, 80; 6, 3, 157, 90]
X = input('指标矩阵A='); %%输入判断矩阵
[n,m] = size(X);
disp(['共有' num2str(n) '个评价对象,' num2str(m) '个评价指标'])
Judge = input(['这' num2str(m) '个评价指标是否需要经过正向化处理,需要请输入1,不需要请输入0:']) ;
if Judge == 1
Position = input('请输入需要进行正向化处理的指标所在的列.例如第2、3、6三列需要处理,那么你需要输入[2,3,6]:'); %[2,3,4]
disp('请输入需要处理的这些列的指标类型(1:极小型, 2:中间型, 3:区间型)');
Type = input('例如:第2列是极小型, 第3列是区间型, 第6列是中间型,就输入[1, 3, 2]:'); %[1,2,3]
%注意,Position和Type是两个同纬度的行向量
for i = 1 : size(Position,2)
%循环的次数
X(:,Position(i)) = Positivization(X(:,Position(i)),Type(i),Position(i));
% Positivization()是自己定义的函数,作用是进行正向化
% 第一个参数是要正向化处理的那一列向量X(:,Position(i))
% 第二个参数是对应这一列的指标类型
% 第三个参数是告诉函数我们正在处理的是原始矩阵的哪一列
% 该函数有一个返回值,它返回正向化之后的指标,我们可以将其直接赋值给原始处理的那一列向量
end
disp('正向化后的矩阵X = ')
disp(X)
else
end
% 矩阵标准化
for i = 1 : m
X(:,i) = X(:,i)./(sum(X(:,i).^2).^(1/2)); %Z = X ./ repmat(sum(X.*X).^0.5, n, 1);
end
disp('标准化之后的矩阵:')
disp(X)
% 计算得分
% 求每一列的最大值
maxc = max(X);
minc = min(X);
DI_max = zeros(n,1);
DI_min = zeros(n,1);
for i = 1 : n
DI_max(i) = (sum((maxc - X(i,:)).^2)).^(1/2); %DI_max = sum([(Z - repmat(max(Z), n, 1)) .^2 ], 2) .^0.5;
DI_min(i) = (sum((minc - X(i,:)).^2)).^(1/2);
end
% 求出的分
SI = DI_min ./ (DI_max + DI_min);
% 归一化
Stand_S = SI ./ (sum(SI)) *100;
disp('最终得分为:')
disp(Stand_S)
[Stand_S,index] = sort(Stand_S,'descend');
disp('最终排名为:')
disp(index)
Matlab中sort()函数的应用。
% sort(A)若A是向量不管是行还是列向量,默认都是对A进行升序排列,sort(A,'descend')是降序排列
% sort(A)若A是矩阵,默认对A的各列进行升序排列
% sort(A,dim)
% dim=1时,等效sort(A)
% dim=2时,表示对A中各行元素升序排列
% A = [2,1,3,8]
% Matlab中给一个一维向量排序是使用sort函数:sort(A),排列是按升序进行的,代排列的向量是A
% 若欲保留排列前的索引,则可用[sA,index] = sort(sA,'descend'),排序后,sA是排序好的向量,index是向量sA中对A的索引
2.正向化处理函数
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);
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('~~~~~~~~~~~~~~分界线~~~~~~~~~~~~~~~')
end
end
3.极小型正向化函数
function [posit_x] = Min2Max(x)
posit_x = max(x) - x ;
end
4.中间型正向化函数
function [posit_x] = Mid2Max(x,best)
M = max(abs(x - best));
posit_x = 1 - abs(x - best)/M ;
end
5.区间型正向化函数
function [posit_x] = Inter2Max(x,a,b)
M = max((a - min(x)),(max(x) - b));
posit_x = zeros(size(x,1),1); %创建0矩阵,size(x,1)行1列;ones(3)->创建3*3的单位矩阵
for i = 1 : size(x,1)
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
在矩阵运算中,可以使用 repmat()函数,减少循环语句,提高内存的使用效率和代码运行速度。
二、代码实现----python
1.主函数
import numpy as np
n = int(input("有几个评价对象:")) # 3
m = int(input("有几个评价指标:")) # 4
kind = input("请输入评价指标的类型").split(" ") # 1 2 3 :1是极小型, 2是区间型, 3是中间型
A = np.zeros(shape=(n,m))
for i in range(n):
A[i] = input("请输入指标矩阵:").split(" ")
A[i] = list(map(float, A[i])) # 将矩阵A转化成float型,并转化成列表
Judge = input("这" + str(m) + "个评价指标是否需要经过正向化处理,需要请输入1,不需要请输入0:")
if Judge == '1':
position = input('请输入需要进行正向化处理的指标所在的列.例如第2、3、6三列需要处理,那么你需要输入[2 3 6]:').split(' ') #[1 2 3]
Position = list(map(int,position))
for i in range(len(Position)):
#循环的次数
A[:,Position[i]] = Positivization(A[:,Position[i]],kind[i],Position[i])
# Positivization()是自己定义的函数,作用是进行正向化
# 第一个参数是要正向化处理的那一列向量X(:,Position(i))
# 第二个参数是对应这一列的指标类型
# 第三个参数是告诉函数我们正在处理的是原始矩阵的哪一列
# 该函数有一个返回值,它返回正向化之后的指标,我们可以将其直接赋值给原始处理的那一列向量
print(A)
python中使用input()读取键盘输入时,得到的数据类型是字符串,可以使用以下代码,将字符串转化为矩阵:
import numpy as np
A = np.zeros(shape=(n,m))
# n, m 均在上文有定义
for i in range(n):
A[i] = input("请输入指标矩阵:").split(" ")
A[i] = list(map(float, A[i])) # 将矩阵A转化成float型,并转化成列表
2.正向化函数
def Positivization(x,kind,position):
if kind == '1':
print("第", int(position) + 1, "列向量是极小型,需要进行正向化")
print("正在进行正向化处理")
posit_x = Min2Max(x)
print("正向化处理完成")
print("~~~~~~~~~~分割线~~~~~~~~~")
elif kind == '2':
print("第", int(position) + 1, "列向量是中间型,需要进行正向化")
best = int(input("请输入最优值:"))
print("正在进行正向化处理")
posit_x = Mid2Max(x, best)
print("正向化处理完成")
# print(A[:,2])
print("~~~~~~~~~~分割线~~~~~~~~~")
elif kind == '3':
print("第", int(position) + 1, "列向量是区间型,需要进行正向化")
a = int(input("请输入区间下限:"))
b = int(input("请输入区间上限:"))
print("正在进行正向化处理")
posit_x = Inter2Max(x, a, b)
print("正向化处理完成")
print("~~~~~~~~~~分割线~~~~~~~~~")
return posit_x
3.极小型正向化函数
def Min2Max(x):
posit_x = max(x) - x
return posit_x
4.中间型正向化函数
def Mid2Max(x, best):
M = max(abs(x - best))
posit_x = 1 - abs(x - best)/M
return posit_x
5.区间型正向化函数
def Inter2Max(x, a, b):
M = max((a - min(x)), (max(x) - b))
posit_x = np.zeros(n) #创建0向量(1*n)
for i in range(n):
if x[i] < a:
posit_x[i] = 1 - (a - x[i]) / M
elif x[i] > b:
posit_x[i] = 1 - (x[i] - b ) / M
else:
posit_x[i] = 1
return posit_x
总结
本文介绍了TOPSIS法的使用,并分别使用Matlab和python进行代码编写。
标签:disp,函数,TOPSIS,python,矩阵,Matlab,posit,input,正向 From: https://blog.csdn.net/m0_65032457/article/details/140724392