熵权法(变异系数法)
一种客观赋权方法,它根据指标的变异程度来确定指标的权重,变异程度越大,说明该指标所包含的信息量越大,相应的权重也就越大。以下是熵权法的详细介绍:
概率与信息量的关系
概率P(x)越小,信息量I(x)越大,原先信息越不靠谱
概率P(x)越大,信息量I(x)越小,原先信息越靠谱
比如一个人,给大家的第一印象是一个老好人,结果一段时间后,大家发现他是一个腹黑man,那么一开始我们掌握的信息就少,获得的就越多.这部分就越重要.
反过来,一个一直在大家心目中的形象不太好的人,做出一些坏事,我们通过这个事情获得的就很少,因为我们一开始就已经掌握了
所以
信息熵:平均而言发生一个时间我们得到信息量的大小
当p(xi)都相等时,H(x)最大,=In (n)
形象的说,就是每一个事情的概率都是一样的,所以你要获得新的信息量也都差不多,所以你面对同等概率的选择,对你来说,选谁你的期望都是一样的,你就无法通过这个选择获取更多的信息
Eg:我们已知外面有一个人请问他是男是女?
显然,50%的概率是男,50%概率是女 ,此时的H(s)=-0.5*log2 0.5 - 0.5*log2 0.5
这里的logn 的n是对象数
但是如果我们知道了外面的人在抽烟,根据网上的数据
那么就会有5/6的概率是男生
所以信息熵的本质就是我们所期望的掌握的信息的量
之后以下面的例题来分析:
甘雨同学毕业后参加相亲,现有表中5位候选人,她想从中挑出一位如意郎君,现请你帮她为年龄、身高、长相、学历、收入分配权重,进而求得最后总分,最高分者就是甘雨的结婚对象.
基本原理
1,数据准备:
假设我们有个m评价对象,n个评价指标,构成原始数据矩阵X=(xij),大小是m*n,其中xij表示第i个评价对象在第j个评价指标上的原始数据。
(也就是上面的表格)
2,数据标准化
由于不同指标的量纲和数量级可能不同,需要对原始数据进行标准化处理,以消除量纲的影响。标准化的方法根据指标的性质分为正向/极大型指标(效益指标,越大越好)和负向/极小型指标(成本指标,越小越好):
(1)正向化处理:
显然,上面的数据中,长相和学历,收入什么的都应该是正向指标,但是具体的也不一定都是越高越好的,比如说身高,要是什么3米就太高了,还有颜值可能也不需要太高,可能红颜祸水,
在这里,我们的甘雨同学的标准是,越年轻越好,学历越高越好,收入越高越好,身高最好180,长相最好80-90,这里的年龄因为是越小越好,所以我们要进行一下正向化的处理,一,将极小型数据转化为极大型数据:
[我感觉这个例子不太好,1岁那岂不是更年轻了(不是)但是还是按照up的记了)
二,中间型的指标,身高180最好这种事中间型指标,也需要正向化:
三,区间型指标:像长相这种80-90这种在某个区间的也需要正向化
下面假设区间是[a,b]
这里的M:
按照上面的步骤,我们把所有的数据正向化了
(2)标准化处理
假设有4个数.,那么对应得到的标准化后的数据就是
标准化后得到的矩阵就是标准化的矩阵Z ,
如果z中有负元素,那么
然后计算各个方案的对应的指标,在整个指标的比重.我们就把这个看作是概率,然后就可以
计算熵权了
3,计算信息熵和熵权
为了直接获得[0,1]的数据,我们将信息熵转换为
因为信息熵越大,信息效用越低,所以信息效用值 d = 1-e
最后得出的是:
下面是代码
(来自b站大师兄):
先是一些正向化的代码:
(1)极小型转换为极大型:
function [res] = Min2Max(X)
res = max(X) - X;
end
(2)中间型转换为极大型:
function [res] = Mid2Max(X, best)//传入向量和最大的数
M = max(abs(X - best));
res = 1 - abs(X - best)/M;
end
(3)区间型转换为极大型
function [res] = Int2Max(X, a, b)
M = max(a - min(X), max(X) - b);
for i = 1 : size(X)
if(X(i) < a)
X(i) = 1 - (a - X(i))/M;
elseif (X(i) >= a && X(i) <= b)
X(i) = 1;
elseif (X(i) > b)
X(i) = 1 - (X(i) - b)/M;
end
end
res = X;
end
disp('***************正在进行正向化...***************');
vec = input('请输入要正向化的向量组,请以数组的形式输入,如[1 2 3]表示1,2,3列需要正向化,不需要正向化请输入-1\n') %注意输入函数这里是单引号
if (vec ~= -1)
for i = 1 : size(vec,2)
flag = input(['第' num2str(vec(i)) '列是哪类数据(【1】:极小型 【2】:中间型 【3】:区间型),请输入序号:\n']);
if(flag == 1)%极小型
X(:,vec(i)) = Min2Max(X(:,vec(i)));
elseif (flag == 2) % 注意这里的else和if是连在一起的
best = input('请输入中间型的最好值:\n');
temp = X(:,vec(i));
X(:,vec(i)) = Mid2Max(X(:,vec(i)), best);
elseif (flag == 3)
arr = input('请输入最佳区间,按照“[a,b]”的形式输入:\n');
X(:,vec(i)) = Int2Max(X(:,vec(i)), arr(1), arr(2));
end
end
disp('所有的数据均已完成正向化!')
end
%% 标准化
disp('***************正在进行标准化...***************');
[n,m] = size(X);
% 先检查有没有负数元素
isNeg = 0;
for i = 1 : n
for j = 1 : m
if(X(i,j) < 0)
isNeg = 1;
break;
end
end
end
if (isNeg == 0)
squere_X = (X.*X);
sum_X = sum(squere_X,1).^0.5; %按列求和,再开方
stand_X = X./repmat(sum_X, n, 1);
else
max_X = max(X,[],1); %按照列找出最大元素
min_X = min(X,[],1); %按照列找出最小元素
stand_X = X - repmat(min_X,n,1) ./ (repmat(max_X,n,1) - repmat(min_X,n,1));
end
disp('标准化完成!')
%% 计算样本概率、信息熵和熵权
disp('***************正在用熵权法确定权值...***************');
P = stand_X ./ repmat(sum(stand_X),n,1);
% 由于ln(0)没有定义,所以我们需要人为的把概率为0的手动指定为一个接近与0的数
for i = 1 : n
for j = 1 : m
if(P(i,j) == 0)
P(i,j) = 0.00001;
end
end
end
H_x = sum(-P .* log(P)); %注意在MATLAB中,想要算ln(x)应该输入log(x);想要算lg(x)则应该输入log10(x)
e_j = H_x ./ log(n);
d_j = 1 - e_j;
%进行归一化,获得熵权
disp('熵权完成,权值为:');
w = d_j ./ sum(d_j)