如下内容是根据B站清风老师数学建模视频作的笔记(B站指路:数学建模优劣解距离法TOPSIS模型)html
TOPSIS法(优劣解距离法)是一种经常使用的综合评价方法,其能充分利用原始数据的信息,其结果能精确地反应法各评价方案之间的差距。web
指标名称 | 指标特色 | 例子 |
---|---|---|
极大型(效益型)指标 | 越大(多)越好 | 成绩、GDP增速 |
极小型(成本型)指标 | 越小(少)越好 | 费用、坏品率、污染程度 |
中间型指标 | 越接近某个值越好 | 水质量评估时的PH值 |
区间型指标 | 落在某个区间最好 | 体温、水中植物性养分物量 |
所谓将原始矩阵正向化,就是要将全部的指标类型统一转化为极大型指标(转化的函数形式不惟一)。app
指标类型的转换:ide
公式: max - x (若是全部元素均为正数,那么可使用 svg
中间型指标 -> 极大型指标函数
是一组中间型指标序列,且最佳的数值为
,那么正向化的公式以下:
spa
区间型指标 -> 极大型指标code
是一组区间型指标序列,且最佳的区间为[a, b] ,那么正向化的公式以下:
orm
标准化的目的是消除不一样指标量纲的影响。视频
假设有 n 个要评价的对象,m 个评价指标(已经正向化)构成的正向化矩阵以下:
那么,对其标准化的矩阵记为Z, Z中的每个元素:
即:
假设有n个要评价的对象,m个评价指标的标准化矩阵:
定义最大值:
定义最小值:
定义第 个 个评价对象与最大值的距离
定义第 个 个评价对象与最小值的距离
能够计算得出第 个 个评价对象未归一化的得分:
显然 , 且 越大,越接近最大值
如下是跟着视频敲的代码
topsis.m
% 注意:代码和数据要放在同一个目录下 clear;clc load data_water_quality.mat %% 第二步:判断是否须要正向化 [n, m] = size(X); disp(['共有' num2str(n) '个评价对象,' num2str(m) '个评价指标']) Judge = input(['这' num2str(m) '个指标是否须要通过正向化处理,须要请输入1,不须要请输入0:']); if Judge == 1 Position = input('请输入须要正向化处理的指标所在的列,例如第二、三、6列须要处理,那么须要输入[2,3,6]: '); %[2,3,4] disp('请输入须要处理的这些列的指标类型(1:极小型,2:中间型,3:区间型') Type = input('例如:第2列是极小型,第三列是区间型,第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)) % 第二个参数是对应的这一列的指标类型 % 第三个参数是告诉函数咱们正在处理的是原始矩阵中的哪一列 % 该函数有一个返回值,它返回正向化以后的指标,咱们能够将其直接赋值给咱们原始要处理的那一列向量 end disp('正向化后的矩阵 X = ') disp(X) end %% 第三步:对正向化后的矩阵进行标准化 Z = X ./ repmat(sum(X .* X) .^ 0.5, n, 1); disp('标准化矩阵 Z = ') disp(Z) %% 第四步:计算与最大值的距离和最小值的距离,并算出得分 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) stand_S = S / sum(S) [sorted_S, index] = sort(stand_S, 'descend')
Positivization.m
function [posit_x] = Positivization(x, type, i) 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); %调用Mid2Max函数来正向化 disp(['第' num2str(i) '列中间型正向化处理完成']) disp('---------------------分界线---------------------') elseif type == 3 %区间型 disp(['第' num2str(i) '是区间型']) a = input('请输入区间的下界: '); b = input('请输入区间的上界: '); posit_x = Inter2Max(x, a, b); %调用Inter2Max函数来正向化 disp(['第' num2str(i) '列区间型正向化处理完成']) disp('---------------------分界线---------------------') else disp('没有这种类型的指标,请检查Type向量中是否有除了一、二、3以外的值') end end
Min2Max.m
function [posit_x] = Min2Max(x) posit_x = max(x) - x; % 若是x所有都大于0,也能够这样正向化:posit_x = 1/x; end
Mid2Max.m
function [posit_x] = Mid2Max(x, best) M = max(abs(x-best)); posit_x = 1 - abs(x-best)/M; end
Inter2Max.m
function [posit_x] = Inter2Max(x, a, b) r_x = size(x, 1); M = max([a-min(x), max(x)-b]); posit_x = zeros(r_x, 1); %初始化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