🤵♂️ 个人主页:@艾派森的个人主页
✍🏻作者简介:Python学习者
🐋 希望大家多多支持,我们一起进步!😄
如果文章对你有帮助的话,
欢迎评论 💬点赞👍🏻 收藏 📂加关注+
目录
问题的提出
熵权法
基本概念
基本步骤
①数据标准化
②计算概率矩阵P
③计算熵权
Python代码实现
问题的提出
根据前几篇文章我们可以知道,评价类模型最后根据各指标进行打分时因各指标的重要性不同往往需要权重,在层次分析法和TOPSIS法里权重都是主观得到的(主观评价、查文献等),那有没有更为客观的方法得到权重呢?
我们继续回到给明星A找对象这个问题上,这里我们对身高这个指标做了一些改动。
思考:观察候选人的数据我们可以发现,A、B、C三人的身高是极为接近的,那么对于找对象来说这个指标是不是就不重要了呢?而对于体重这个指标来说,三人相差较大,那么找对象是不是就要多考虑下这个指标?
熵权法
基本概念
熵权法,物理学名词,按照信息论基本原理的解释,信息是系统有序程度的一个度量,熵是系统无序程度的一个度量;根据信息熵的定义,对于某项指标,可以用熵值来判断某个指标的离散程度,其信息熵值越小,指标的离散程度越大,该指标对综合评价的影响(即权重)就越大,如果某项指标的值全部相等,则该指标在综合评价中不起作用。因此,可利用信息这个工具,计算出各个指标的权重,为多指标综合评价提供依据。
- 熵权法是一种客观的赋权方法,它可以靠数据本身得出权重
- 依据的原理:指标的变异程度越小,所反映的信息量也越少,其对应的权值也应该越低。
基本步骤
①数据标准化
②计算概率矩阵P
③计算熵权
我们继续帮明星A选对象,首先把原始指标矩阵正向化,这里我们还是使用之前没修改过的数据
将指标正向化后如下:
接着进行正向矩阵标准化:
计算概率矩阵P
计算熵权
得出的熵权结果如下:
Python代码实现
import numpy as np # 导入numpy库,并简称为np
# 定义一个自定义的对数函数mylog,用于处理输入数组中的零元素
def mylog(p):n = len(p) # 获取输入向量p的长度lnp = np.zeros(n) # 创建一个长度为n,元素都为0的新数组lnpfor i in range(n): # 对向量p的每一个元素进行循环if p[i]==0: # 如果当前元素的值为0lnp[i]=0 # 则在np中对应位置也设置为0,因为Log(0)是未定义的,这里我们规定为0else:lnp[i]= np.log(p[i]) # 如果p[i]不为0,则计算其自然对数并赋值给lnp的对应位置return lnp # 返回计算后的对数效组
# 定义一个指标矩阵X
X = np.array([[9,0,0,0],[8,3,0.9,0.5],[6,7,0.2,1]])
# 对矩阵X进行标准化处理,得到标准化矩阵Z
Z = X/np.sqrt(np.sum(X*X,axis=0))
print("标准化矩阵Z=")
print(Z)# 计算熵权所需的变量和矩阵初始化
n,m = Z.shape # 获取标准化矩阵Z的行数和列数
D = np.zeros(m) # 初始化一个长度为m的数组D,用于保存每个指标的信息效用值
# 计算每个指标的信息效用值
for i in range(m): # 历Z的每一列x = Z[:,i] # 获职Z的第i列,即第i个指标的所有数据p = x/np.sum(x) # 对第i个指标的数据进行归一化处理,得到概率分布p# 使用自定义的mylog的数计算p的对数。需要注意的是,如果p中含有0,直接使用np.1og会得到-inf,这里使用自定义函数避免这个问题e = -np.sum(p * mylog(p))/np.log(n) # 根据熵的定义计算第i个指标的信息熵eD[i] = 1-e # 根据信息效用值的定义计算D[i]
# 根据信息效用值计算各指标的权重
W = D/np.sum(D) # 将信息效用值D归一化,得到各指标的权重W
print("权重W=",W)
在上面的代码中,我们需要传入正向化后的指标矩阵X = np.array([[9,0,0,0],[8,3,0.9,0.5],[6,7,0.2,1]])
运行结果如下:
在用熵权法得到指标权重后,我们可以计算出加上权重后的标准化矩阵
temp_list = []
for i,j in zip(Z.T,W):temp_list.append(i*j)
import pandas as pd
new_Z = pd.DataFrame(data=temp_list).T.to_numpy()
print("加上权重后的标准化矩阵为:\n{}".format(new_Z)) # 打印加上权重后的标准化后的矩阵new_X
运行结果如下:
最后我们可以使用前面TOPSIS法中讲到的计算标准化后的得分
# 计算与最大值和最小值的距离,并算出得分
tep_max = new_Z.max(0) # 得到Z中每列的最大值
tep_min = new_Z.min(0) # 每列的最小值
tep_a = new_Z - np.tile(tep_max, (n, 1)) # 将tep_max向下平铺n行,并与Z中的每个对应元素做差
tep_i = new_Z - np.tile(tep_min, (n, 1)) # 将tep_max向下平铺n行,并与Z中的每个对应元素做差
D_P = ((tep_a ** 2).sum(axis=1)) ** 0.5 # D+与最大值的距离向量
D_N = ((tep_i ** 2).sum(axis=1)) ** 0.5
S = D_N / (D_P + D_N) # 未归一化的得分
std_S = S / S.sum(axis=0)
sorted_S = np.sort(std_S, axis=0)
print('标准化后的得分:',[x*100 for x in std_S]) # 打印标准化后的得分
运行结果如下:
从结果可以看出,最后还是候选人B得分最高。
资料获取,更多粉丝福利,关注下方公众号获取