草庐IT

基于熵权法的topsis分析(包含matlab源码以及实例)

michelle emma 2023-07-17 原文

            

目录

一、算法简述

         1.topsis分析法

         2.熵权法

         3.两种算法的结合

二、算法步骤

         1.判断指标类型

         2.数据正向化

         3.正向化矩阵标准化

         4.计算概率矩阵P

         5.计算各个指标的信息熵

         6.计算信息效用值

         7.计算熵权

         8.计算最优距离和最劣距离

         9.计算未归一化得分以及归一化得分

三、MATLAB代码实现

        1.主函数topsis.m

        2.正向化函数 Positivization.m

        3.熵权法函数 Entropy_Method.m

        4.ln函数 mylog.m

          写在前面

                 本篇不介绍熵权法以及topsis分析法的详细原理 若想了解请移步其他博客!!!

                恰恰相反,本篇为懒人福利,适用于数学建模等需要快速解决问题的赛事。

一、算法简述

       1.topsis分析法

            topsis算法是一种常见的综合评价办法,适用于有多个指标时的方案选择问题,如下图所示

            ps:以下数据为自行创造 仅用于讲解

方案\指标可采矿量基建投资土地PH值人员
方案1521250005.745
方案2361526004.032
方案3501154125.043
方案4403832004.338
方案5446236004.840

            通过topsis分析法我们可以通过优劣分析,为五个方案分别赋予一个评分,显然评分越高,综合考量下来优势越大。

        2.熵权法

                我们已经知道topsis分析法可以给每个方案一个评分,但这个评分是在各个指标所占权重相同的前提下来算的,但我们遇到的问题大部分肯定有的指标重要,有的不那么重要,我们又不能去主观给他赋权重,这个问题应该怎么解决?没错,熵权法可以!

                熵权法是一种客观赋权方法,通过计算指标的信息熵,根据相对变化程度对整体的影响来决定指标权重。(不懂不要紧 会用就行)

        3.两种算法的结合

                了解了两种算法的基本原理,我们很容易想到,可以通过熵权法算出各指标的权重,进而通过topsis分析法进行评分,就能得到可信度较高的结果

二、算法步骤

        1.判断指标类型

                topsis模型一般是在所有指标均为极大型指标(数据越大越好)的基础上进行运算的,因此要判断各个指标都是什么类型,方便后面进行数据正向化。

                一般的常见类型有

                极大型(数据越大越好) 比如上方表格中的可采矿量

                极小型(数据越小越好)  比如上方表格中的基建投资

                中间型(数据稳定在某个固定的值最好) 比如上方表格里的ph最好保持在4.3

                区间型(数据在某个区间内最好)比如上方表格中的人员最好在[30,40]之间

         2.数据正向化

                极小型数据(PS:当数据不全为正数时 只能使用第二个公式)

                        

                  上面表格的基建投资极小型数据 我们采用第二个公式来正向化

方案\基建投资正向化前正向化后
方案15000412
方案226002812
方案354120
方案432002212
方案536001812

                中间型数据

                首先应该输入一个中间最优值再进行正向化

                        

                上面表格的土地PH值中间型数据 我们的是4.3 

方案\土地PH正向化前正向化后
方案15.70
方案24.00.7857
方案35.00.5
方案44.31
方案54.80.6429

                区间型数据

                首先应该输入区间下限a和区间上限b再进行正向化

                          

                

                 上面表格的人员指标为区间型数据 我们的下限a是30 上限b是40  M是5

方案\人员正向化前正向化后
方案1450
方案2321
方案3430.4
方案4381
方案5401

                正向化结束的矩阵称为正向化矩阵。如下表

方案\指标可采矿量基建投资土地PH人员
方案1521241200
方案2361528120.78571
方案3501100.50.4
方案44038221211
方案5446218120.64291

         3.正向化矩阵标准化

                正向矩阵标准化是为了消除不同量纲的影响。

                        

方案\指标可采矿量基建投资土地PH人员
方案10.51720.102200
方案20.3587

0.6975

0.52030.5625
方案30.497200.33110.2250
方案40.40070.54870.66220.5625
方案50.44280.44950.42570.5625

                这里得到的标准化矩阵要求所有数据必须全部大于等于0,如果有负数,需要按照以下方式重新进行标准化

                

            PS:4-7步是熵权法确定指标权重的步骤 如果想实现各指标权重相同  默认是1/m

         4.计算概率矩阵P

                                 

方案\指标可采矿量基建投资土地PH人员
方案10.23330.056800
方案20.16180.38800.26830.2941
方案30.224300.17070.1176
方案40.18080.30520.34150.2941
方案50.19970.25000.21950.2941

         5.计算各个指标的信息熵

                        

                PS:由于概率矩阵中可能存在数值为0,但ln(0)为负无穷 我们这里将ln(0)设为0

指标可采矿量基建投资土地PH人员
信息熵0.99450.76990.84160.8275

         6.计算信息效用值

                        

指标可采矿量基建投资土地PH人员
信息效用值0.00550.23010.15840.1726

         7.计算熵权

                        

指标可采矿量基建投资土地PH人员
熵权0.00980.40610.27950.3047

        8.计算最优距离和最劣距离

                定义最大值

指标可采矿量基建投资土地PH人员
0.51720.69750.66220.5625

                定义最小值

   

指标可采矿量基建投资土地PH人员
0.3587000

                定义第i个(i=1,2, ... ,n)评价对象与最大值的距离

                        

                 定义第i个(i=1,2, ... ,n)评价对象与最小值的距离

                        

方案\距离
方案10.60240.0670

方案2

0.07660.6080
方案30.51270.2151
方案40.09550.5841
方案50.20170.4787

         9.计算未归一化得分以及归一化得分

                未归一化得分

                        

                归一化得分(分数相加等于1)

                        

方案\距离
方案10.10010.0352

方案2

0.88800.3120
方案30.29550.1038
方案40.85940.3019
方案50.70360.2472

                        由最终的可知,五个方案的的排名为5,1,4,2,3

三、MATLAB代码实现

        代码部分共有四个.m文件 一个主文件 三个函数

1.主函数topsis.m

[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]:  ');
    disp('请输入这些列分别是什么指标类型(1:极小型 2:中间型 3:区间型)')
    Type=input('比如 2 3 6列分别是极小型 区间型 中间型 则输入[1,3,2]:  ');
    for i=1:size(Position,2)
        X(:,Position(i))=Positivization(X(:,Position(i)),Type(i),Position(i));
    end
    disp('正向化后的矩阵为 X=');
    disp(X);
end
%标准化
Z = X ./ repmat(sum(X.*X) .^ 0.5, n, 1);
disp('标准化矩阵 Z = ')
disp(Z)



disp("请输入是否需要增加权重向量,需要输入1,不需要输入0")
Judge = input('请输入是否需要增加权重: ');
if Judge == 1
    if sum(sum(Z<0))>0
        disp('标准化矩阵中存在负数 正在重新标准化')
        for j=1:m
            minn=min(Z(:,j));
            maxx=max(Z(:,j));
            for i=1:n
                Z(i,j)=(Z(i,j)-minn)/(maxx-minn)
            end
        end
        disp('标准化完成 矩阵Z=  ');
        disp(Z);
    end
    W = Entropy_Method(Z);
    disp('熵权法确定的权重为:');
    disp(W);        
else
    W = ones(1,m) ./ m ; %如果不需要加权重就默认权重都相同,即都为1/m
end



D_P = sum([W .* (Z - repmat(max(Z),n,1)) .^ 2 ],2) .^ 0.5;%最优距离
D_N = sum([W .* (Z - repmat(min(Z),n,1)) .^ 2 ],2) .^ 0.5;%最劣距离
S = D_N ./ (D_P+D_N);%相对接近度(可用来当得分)   
disp('最后的得分为:')
stand_S = S / sum(S)%得分归一化 最后各方案得分相加为1
[sorted_S,index] = sort(stand_S ,'descend');
disp('按得分从高到底排列方案 分别为:  ');
disp(index);%方案排名


2.正向化函数 Positivization.m

%正向化 Positivization 三个输入变量分别为目前处理的列向量 该列的指标类型 目前处理的是第几列
%输出变量为正向化后的列向量
function [posit_x]=Positivization(x,type,i)
    if type==1 %极小型
        posit_x=max(x)-x;
        %posit_x=1./x 如果该列数据全部大于0 也可以这样正向化
    elseif type==2%中间型
        best=input('请输入最佳的值:  ');
        M=max(abs(x-best));
        posit_x=1-abs(x-best)/M;
    elseif type==3%区间型
        a=input('请输入区间下限:  ');
        b=input('请输入区间上限:  ');
        MM=max(a-min(x),max(x)-b);
        posit_x = zeros(size(x,1),1);
        for i=1:size(x,1)
            if x(i)<a
                posit_x(i)=1-(a-x(i))/MM;
            elseif x(i)>b
                posit_x(i)=1-(x(i)-b)/MM;
            else
                posit_x(i)=1;
            end
        end
    else 
        disp('请正确输入指标类型')
    end
end

3.熵权法函数 Entropy_Method.m

%计算权重
function [W] = Entropy_Method(Z)
    [n,m]=size(Z);
    d=zeros(1,m);
    for i=1:m
        x = Z(:,i);
        p = x./sum(x);%概率矩阵
        e = -sum(p .* mylog(p)) / mylog(n);%信息熵
        d(i)=1-e;%信息效用值
    end
    W=d./sum(d);%熵权
end

 4.ln函数 mylog.m

function [lnp] =  mylog(p)
n = length(p);   % 向量的长度
lnp = zeros(n,1);   % 初始化最后的结果
    for i = 1:n   % 开始循环
        if p(i) == 0   % 如果第i个元素为0
            lnp(i) = 0;  % 那么返回的第i个结果也为0
        else
            lnp(i) = log(p(i));  
        end
    end
end

注:本篇文章为自己系统了解后写下,不保证不会出现问题。大家如果对文章存在困惑或者质疑 ,欢迎在评论区留言。

参考链接

熵值法与TOPSIS法以及两者结合 作者:卖山楂啦prss

数学建模之熵权法——基于Topsis模型 作者:我本无忧

基于熵权法的Topsis模型(清风数学建模课后笔记) 作者:weixin_57449924   

有关基于熵权法的topsis分析(包含matlab源码以及实例)的更多相关文章

  1. ruby - 什么是填充的 Base64 编码字符串以及如何在 ruby​​ 中生成它们? - 2

    我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%

  2. ruby - 检查 "command"的输出应该包含 NilClass 的意外崩溃 - 2

    为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar

  3. ruby-on-rails - 如何使用 instance_variable_set 正确设置实例变量? - 2

    我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击

  4. ruby 正则表达式 - 如何替换字符串中匹配项的第 n 个实例 - 2

    在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如5到15之间)的子字符串,并将该实例替换为另一个字符串“X”。我的测试字符串s="1foo100bar10gee1"我的初始模式是1个或多个数字的任何字符串,例如,re=Regexp.new(/\d+/)matches=s.scan(re)给出["1","100","10","1"]如果我想用“X”替换第N个匹配项,并且只替换第N个匹配项,我该怎么做?例如,如果我想替换第三个匹配项“10”(匹配项[2]),我不能只说s[matches[2]]="X"因为它做了两次替换“1fooX0barXg

  5. ruby - 检查字符串是否包含散列中的任何键并返回它包含的键的值 - 2

    我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案

  6. ruby-on-rails - Rails - 从另一个模型中创建一个模型的实例 - 2

    我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案

  7. ruby-on-rails - RSpec:避免使用允许接收的任何实例 - 2

    我正在处理旧代码的一部分。beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)endRubocop错误如下:Avoidstubbingusing'allow_any_instance_of'我读到了RuboCop::RSpec:AnyInstance我试着像下面那样改变它。由此beforedoallow_any_instance_of(SportRateManager).toreceive(:create).and_return(true)end对此:let(:sport_

  8. ruby-on-rails - 使用 ruby​​ 将多个实例变量转换为散列的更好方法? - 2

    我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作:response.instance_variables.eachdo|r|my_hash.merge!(r.to_s.delete("@").intern=>response.instance_eval(r.to_s.delete("@")))end这有效,它将生成{:first="charlie",:last=>"kelly"},但它似乎有点hacky和不稳定。有更好的方法吗?编辑:我刚刚意识到我可以使用instance_variable_get作为该等式的第二部分,但这仍然是主要问题。

  9. 叮咚买菜基于 Apache Doris 统一 OLAP 引擎的应用实践 - 2

    导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵

  10. Matlab imread()读到了什么 (浅显 当复习文档了) - 2

    matlab打开matlab,用最简单的imread方法读取一个图像clcclearimg_h=imread('hua.jpg');返回一个数组(矩阵),往往是a*b*cunit8类型解释一下这个三维数组的意思,行数、数和层数,unit8:指数据类型,无符号八位整形,可理解为0~2^8的数三个层数分别代表RGB三个通道图像rgb最常用的是24-位实现方法,即RGB每个通道有256色阶(2^8)。基于这样的24-位RGB模型的色彩空间可以表现256×256×256≈1670万色当imshow传入了一个二维数组,它将以灰度方式绘制;可以把图像拆分为rgb三层,可以以灰度的方式观察它figure(1

随机推荐