熵权法(内含python完整代码)

背景:

依然是熟悉的评价决策类模型

评价类模型最后根据各指标进行打分时因各指标的重要性不同往往需要权重,但是在层次分析法和TOPSIS法里权重都是主观得到的(主观评价、查文献等),那有没有更为客观的方法得到权重呢?

那就是我们今天的主角啦---熵权法

  • 观察候选人的数据我们可以发现,A、B、C三人的身高是极为接近的,那么对于找对象来说这个指标是不是就不重要了呢?
  • 而对于体重这个指标来说,三人相差较大,那么找对象是不是就要多考虑下这个指标?

熵权法,物理学名词,按照信息论基本原理的解释,信息是系统有序程度的一个度量,熵是系统
无序程度的一个度量;根据信息恼的定义,对于某项指标,可以用熵值来判断某个指标的离散程度,其信息熵值越小,指标的离散程度越大,该指标对综合评价的影响(即权重)就越大,如果某项指标的值全部相等,则该指标在综合评价中不起作用。因此,可利用信息熵这个工具,计算出各个指标的权重,为多指标综合评价提供依据。

熵权法是一种客观的赋权方法,它可以靠数据本身得到权重。
依据的原理:指标的变异程度越小,所反映的信息量也越少,其对应的权值也应该越低。

信息熵:主要是衡量一组符合某个概率分布的数据进行编码,最小的平均编码长度。通俗点说就是发电报所支付的成本费用,工程上就是用最少的字表达最丰富的信息。

信息是为了消除不确定性

例如玩一个猜骰子的游戏:

我告诉你骰子的点数大于0,和大于3,等于5是不是有差别呢?

那么这其中信息量怎么度量呢?

我们再和朋友玩一个游戏

猜一猜小球的数字,你可以问他问题,他只能回答yes or no,为了体现信息的价值,每问一次问题都需要支付朋友一元钱

问的问题:如大于2吗?是1吗?

依照规律模拟信息熵,发现有对数关系。那么为啥我们对数底是为2呢,因为我们游戏内只能回答yes和no

概率越小,信息熵越大,因为排除的不确定性很大。

基本步骤:

具体实现代码

import numpy as np  # 导入numpy库,并简称为np

# 定义一个自定义的对数函数mylog,用于处理输入数组中的零元素
def mylog(p):
    n = len(p)  # 获取输入向量p的长度
    lnp = np.zeros(n)  # 创建一个长度为n,元素都为0的新数组lnp
    for i in range(n):  # 对向量p的每一个元素进行循环
        if p[i] == 0:  # 如果当前元素的值为0
            lnp[i] = 0  # 则在lnp中对应位置也设置为0,因为log(0)是未定义的,这里我们规定为0
        else:
            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)  # 打印标准化矩阵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.log会得到-inf,这里使用自定义函数避免这个问题
    e = -np.sum(p * mylog(p)) / np.log(n)  # 根据熵的定义计算第i个指标的信息熵e
    D[i] = 1 - e  # 根据信息效用值的定义计算D[i]

# 根据信息效用值计算各指标的权重
W = D / np.sum(D)  # 将信息效用值D归一化,得到各指标的权重W

print("权重 W = ")
print(W)  # 打印得到的权重数组W
weighted_average = Z @ W
len_w = len(weighted_average)
sum_w = sum(weighted_average)
for i in range(len_w):
    weighted_average[i] /= sum_w
print("加权平均值为:")
print(weighted_average)

  • 19
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值