目录
写在前面
本篇不介绍熵权法以及topsis分析法的详细原理 若想了解请移步其他博客!!!
恰恰相反,本篇为懒人福利,适用于数学建模等需要快速解决问题的赛事。
topsis算法是一种常见的综合评价办法,适用于有多个指标时的方案选择问题,如下图所示
ps:以下数据为自行创造 仅用于讲解
| 方案\指标 | 可采矿量 | 基建投资 | 土地PH值 | 人员 |
| 方案1 | 5212 | 5000 | 5.7 | 45 |
| 方案2 | 3615 | 2600 | 4.0 | 32 |
| 方案3 | 5011 | 5412 | 5.0 | 43 |
| 方案4 | 4038 | 3200 | 4.3 | 38 |
| 方案5 | 4462 | 3600 | 4.8 | 40 |
通过topsis分析法我们可以通过优劣分析,为五个方案分别赋予一个评分,显然评分越高,综合考量下来优势越大。
我们已经知道topsis分析法可以给每个方案一个评分,但这个评分是在各个指标所占权重相同的前提下来算的,但我们遇到的问题大部分肯定有的指标重要,有的不那么重要,我们又不能去主观给他赋权重,这个问题应该怎么解决?没错,熵权法可以!
熵权法是一种客观赋权方法,通过计算指标的信息熵,根据相对变化程度对整体的影响来决定指标权重。(不懂不要紧 会用就行)
了解了两种算法的基本原理,我们很容易想到,可以通过熵权法算出各指标的权重,进而通过topsis分析法进行评分,就能得到可信度较高的结果
topsis模型一般是在所有指标均为极大型指标(数据越大越好)的基础上进行运算的,因此要判断各个指标都是什么类型,方便后面进行数据正向化。
一般的常见类型有
极大型(数据越大越好) 比如上方表格中的可采矿量
极小型(数据越小越好) 比如上方表格中的基建投资
中间型(数据稳定在某个固定的值最好) 比如上方表格里的ph最好保持在4.3
区间型(数据在某个区间内最好)比如上方表格中的人员最好在[30,40]之间
极小型数据(PS:当数据不全为正数时 只能使用第二个公式)

上面表格的基建投资为极小型数据 我们采用第二个公式来正向化
| 方案\基建投资 | 正向化前 | 正向化后 |
| 方案1 | 5000 | 412 |
| 方案2 | 2600 | 2812 |
| 方案3 | 5412 | 0 |
| 方案4 | 3200 | 2212 |
| 方案5 | 3600 | 1812 |
中间型数据
首先应该输入一个中间最优值再进行正向化

上面表格的土地PH值为中间型数据 我们的是4.3
| 方案\土地PH | 正向化前 | 正向化后 |
| 方案1 | 5.7 | 0 |
| 方案2 | 4.0 | 0.7857 |
| 方案3 | 5.0 | 0.5 |
| 方案4 | 4.3 | 1 |
| 方案5 | 4.8 | 0.6429 |
区间型数据
首先应该输入区间下限a和区间上限b再进行正向化
上面表格的人员指标为区间型数据 我们的下限a是30 上限b是40 M是5
| 方案\人员 | 正向化前 | 正向化后 |
| 方案1 | 45 | 0 |
| 方案2 | 32 | 1 |
| 方案3 | 43 | 0.4 |
| 方案4 | 38 | 1 |
| 方案5 | 40 | 1 |
正向化结束的矩阵称为正向化矩阵。如下表
| 方案\指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 方案1 | 5212 | 412 | 0 | 0 |
| 方案2 | 3615 | 2812 | 0.7857 | 1 |
| 方案3 | 5011 | 0 | 0.5 | 0.4 |
| 方案4 | 4038 | 2212 | 1 | 1 |
| 方案5 | 4462 | 1812 | 0.6429 | 1 |
正向矩阵标准化是为了消除不同量纲的影响。

| 方案\指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 方案1 | 0.5172 | 0.1022 | 0 | 0 |
| 方案2 | 0.3587 | 0.6975 | 0.5203 | 0.5625 |
| 方案3 | 0.4972 | 0 | 0.3311 | 0.2250 |
| 方案4 | 0.4007 | 0.5487 | 0.6622 | 0.5625 |
| 方案5 | 0.4428 | 0.4495 | 0.4257 | 0.5625 |
这里得到的标准化矩阵要求所有数据必须全部大于等于0,如果有负数,需要按照以下方式重新进行标准化。

PS:4-7步是熵权法确定指标权重的步骤 如果想实现各指标权重相同 默认是1/m
| 方案\指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 方案1 | 0.2333 | 0.0568 | 0 | 0 |
| 方案2 | 0.1618 | 0.3880 | 0.2683 | 0.2941 |
| 方案3 | 0.2243 | 0 | 0.1707 | 0.1176 |
| 方案4 | 0.1808 | 0.3052 | 0.3415 | 0.2941 |
| 方案5 | 0.1997 | 0.2500 | 0.2195 | 0.2941 |
PS:由于概率矩阵中可能存在数值为0,但ln(0)为负无穷 我们这里将ln(0)设为0
| 指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 信息熵 | 0.9945 | 0.7699 | 0.8416 | 0.8275 |
| 指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 信息效用值 | 0.0055 | 0.2301 | 0.1584 | 0.1726 |
| 指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 熵权 | 0.0098 | 0.4061 | 0.2795 | 0.3047 |
定义最大值
| 指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 0.5172 | 0.6975 | 0.6622 | 0.5625 |
定义最小值
| 指标 | 可采矿量 | 基建投资 | 土地PH | 人员 |
| 0.3587 | 0 | 0 | 0 |
定义第i个(i=1,2, ... ,n)评价对象与最大值的距离
定义第i个(i=1,2, ... ,n)评价对象与最小值的距离
| 方案\距离 | ||
| 方案1 | 0.6024 | 0.0670 |
| 方案2 | 0.0766 | 0.6080 |
| 方案3 | 0.5127 | 0.2151 |
| 方案4 | 0.0955 | 0.5841 |
| 方案5 | 0.2017 | 0.4787 |
未归一化得分
归一化得分(分数相加等于1)
| 方案\距离 | ||
| 方案1 | 0.1001 | 0.0352 |
| 方案2 | 0.8880 | 0.3120 |
| 方案3 | 0.2955 | 0.1038 |
| 方案4 | 0.8594 | 0.3019 |
| 方案5 | 0.7036 | 0.2472 |
由最终的可知,五个方案的的排名为5,1,4,2,3
代码部分共有四个.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);%方案排名
%正向化 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
%计算权重
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
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模型(清风数学建模课后笔记) 作者:weixin_57449924
我正在使用的第三方API的文档状态:"[O]urAPIonlyacceptspaddedBase64encodedstrings."什么是“填充的Base64编码字符串”以及如何在Ruby中生成它们。下面的代码是我第一次尝试创建转换为Base64的JSON格式数据。xa=Base64.encode64(a.to_json) 最佳答案 他们说的padding其实就是Base64本身的一部分。它是末尾的“=”和“==”。Base64将3个字节的数据包编码为4个编码字符。所以如果你的输入数据有长度n和n%3=1=>"=="末尾用于填充n%
为了将Cucumber用于命令行脚本,我按照提供的说明安装了arubagem。它在我的Gemfile中,我可以验证是否安装了正确的版本并且我已经包含了require'aruba/cucumber'在'features/env.rb'中为了确保它能正常工作,我写了以下场景:@announceScenario:Testingcucumber/arubaGivenablankslateThentheoutputfrom"ls-la"shouldcontain"drw"假设事情应该失败。它确实失败了,但失败的原因是错误的:@announceScenario:Testingcucumber/ar
我正在查看instance_variable_set的文档并看到给出的示例代码是这样做的:obj.instance_variable_set(:@instnc_var,"valuefortheinstancevariable")然后允许您在类的任何实例方法中以@instnc_var的形式访问该变量。我想知道为什么在@instnc_var之前需要一个冒号:。冒号有什么作用? 最佳答案 我的第一直觉是告诉你不要使用instance_variable_set除非你真的知道你用它做什么。它本质上是一种元编程工具或绕过实例变量可见性的黑客攻击
在我的应用程序中,我需要能够找到所有数字子字符串,然后扫描每个子字符串,找到第一个匹配范围(例如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
我有一个包含多个键的散列和一个字符串,该字符串不包含散列中的任何键或包含一个键。h={"k1"=>"v1","k2"=>"v2","k3"=>"v3"}s="thisisanexamplestringthatmightoccurwithakeysomewhereinthestringk1(withspecialcharacterslike(^&*$#@!^&&*))"检查s是否包含h中的任何键的最佳方法是什么,如果包含,则返回它包含的键的值?例如,对于上面的h和s的例子,输出应该是v1。编辑:只有字符串是用户定义的。哈希将始终相同。 最佳答案
我有一个正在构建的应用程序,我需要一个模型来创建另一个模型的实例。我希望每辆车都有4个轮胎。汽车模型classCar轮胎模型classTire但是,在make_tires内部有一个错误,如果我为Tire尝试它,则没有用于创建或新建的activerecord方法。当我检查轮胎时,它没有这些方法。我该如何补救?错误是这样的:未定义的方法'create'forActiveRecord::AttributeMethods::Serialization::Tire::Module我测试了两个环境:测试和开发,它们都因相同的错误而失败。 最佳答案
我正在处理旧代码的一部分。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_
我收到格式为的回复#我需要将其转换为哈希值(针对活跃商家)。目前我正在遍历变量并执行此操作: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作为该等式的第二部分,但这仍然是主要问题。
导读:随着叮咚买菜业务的发展,不同的业务场景对数据分析提出了不同的需求,他们希望引入一款实时OLAP数据库,构建一个灵活的多维实时查询和分析的平台,统一数据的接入和查询方案,解决各业务线对数据高效实时查询和精细化运营的需求。经过调研选型,最终引入ApacheDoris作为最终的OLAP分析引擎,Doris作为核心的OLAP引擎支持复杂地分析操作、提供多维的数据视图,在叮咚买菜数十个业务场景中广泛应用。作者|叮咚买菜资深数据工程师韩青叮咚买菜创立于2017年5月,是一家专注美好食物的创业公司。叮咚买菜专注吃的事业,为满足更多人“想吃什么”而努力,通过美好食材的供应、美好滋味的开发以及美食品牌的孵
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