首页 > 编程语言 >【学习笔记】Matlab和python双语言的学习(TOPSIS法)

【学习笔记】Matlab和python双语言的学习(TOPSIS法)

时间:2024-07-27 15:59:01浏览次数:16  
标签:disp 函数 TOPSIS python 矩阵 Matlab posit input 正向

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

文章目录


前言

通过模型算法,熟练对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

相关文章

  • 基于Python flask 的豆瓣电影top250数据评分可视化
    跟着CSDN上学习一下爬虫和简单的可视化分析,最后完成了一个简单的小项目。1.项目简介        基于Pythonflask的豆瓣电影评分可视化。通过采用Python编程语言,使用flask框架搭建影视系统,并使用相关技术实现对豆瓣网站的爬取、数据存储和可视化分析。2、成果展示:......
  • 获取 Python Decimal 的精确十进制字符串表示形式?
    如果我有一个PythonDecimal,我怎样才能可靠地获得数字的精确十进制字符串(即不是科学记数法)表示而不带尾随零?例如,如果我有:>>>d=Decimal('1e-14')我会像:>>>get_decimal_string(d)'0.00000000000001'但是:Decimal类没有任何to_......
  • python datetime timedelta 对于没有小数部分的时间返回 0.0
    我正在使用datetime.timedelta来获取python中进程的持续时间。defget_time_difference(start_time,end_time):time_in_seconds=(end_time-start_time)returnstr(datetime.timedelta(seconds=time_in_seconds))[:-3]文档指出“所有参数都是可选的......
  • 如何运行从我正在编写的另一个 Python 脚本获取命令行参数的 Python 脚本?
    我有一个python3脚本,如下所示:...defmain():parser=argparse.ArgumentParser(description='Performnormalisationchecksonpass2files')parser.add_argument('-p','--parser',action='store',help='parse......
  • Python 抓取 urllib2 HTTP 错误
    我正在尝试抓取一个网站,但我的代码仅在我打开该网站然后刷新它时才有效。我尝试了多种方法,但不断出现以下两个错误:第一个:ValueError:“HTTPError:HTTP错误416:请求的范围无法满足”urlslist=open("list_urls.txt").read()urlslist=urlslist.split("\n")forurlslistinurl......
  • 【Python】利用 face_recognition 库进行人脸检测识别【附完整示例】
    1.背景条件1.1安装所需库首先安装face_recognition和Pillow这两个库。您可以使用以下命令来安装它们:pipinstallface_recognitionPillow-ihttps://pypi.tuna.tsinghua.edu.cn/simple1.2拷贝代码安装完成后,您就可以在本地运行以下提供的代码了。importfac......
  • 太强了,Python+Excel真的是神仙组合!
    本书是由流行开源Python库xlwings的创始人:费利克斯·朱姆斯坦(FelixZumstein)所撰写。他详细阐述了如何将Python与Excel结合使用,让任务自动化,从而实现效率飞跃。为了帮助初学者克服对Python的恐惧,作者特意将教程内容设计成从简单到复杂的顺序进行介绍。这本书PDF共282页,分为4个......
  • 在 Python 中获取精确的 Android GPS 位置
    我尝试在Python中获取Android手机的GPS位置(使用QPython3应用程序)。这种可行,但是Android中似乎有几个LocationProvider:gps:纯gps定位,速度慢,耗能,但非常准确,正是我所需要的。网络:GPS和wifi/小区定位的混合,更快,但不太准确被动......
  • 使用 docker run 将 Python 单击选项传递给 ENTRYPOINT 会出现错误:“在 $PATH 中找不
    我有一个简单的python脚本,我想在docker容器内运行它。它打印一行消息“Hello{name}”。python脚本使用clickCLI界面来定义收件人名称,如果我直接运行它(不使用dockerrun命令),它将如下所示:pythonhello.py-nSmithDockerbuild命令:dockerbuild.-thello:1.......
  • 标题:在 OpenSees Python 中定义具有特定卸载行为的双线性弹塑性材料
    我正在使用Python中的OpenSees,我想定义一种在负载下表现出双线性弹塑性行为的材料。但是,我需要在卸载过程中将材质返回到其原始位置,遵循准确的加载路径。在此处输入图像描述我不确定如何在OpenSees中正确实现卸载行为,我正在寻找实现这一具体材料反应的指导。......