数据处理过程中,数据量越多,模型训练对样本数据学习过程会更好,因此计算权重最好方式是训练模型加权,但实际过程会存在样本数据较小的情况,可以使用熵值法来计算数据。
- 概念解释
权重概念:权重是一个相对的概念,是针对某一指标而言,某一指标的权重是指该指标在整体评价中的相对重要程度。
熵值法是一种客观赋权法,是根据各项指标观测值所提供的信息的大小来确定指标权重。
在信息论中,熵是对不确定性信息的一种度量。信息量越大,不确定性就越小,熵也就越小;信息量越小,不确定性越大,熵也越大。因而利用熵值携带的信息进行权重计算,结合各项指标的变异程度,利用信息熵这个工具,计算出各项指标的权重,为多指标综合评价提供依据。
- 知识补充:
熵 是 统计物理与信息论术语 ,泛指某些 物质系统状态的 一种 量度,某些物质系统状态可能出现的程度。系统 越混乱 ,熵越大 。
假定P(x=xi)=pi
,则 熵 公式如下
其中 n 代表分类问题中 类别个数 。
而 多分类 问题可以转化为 多个二分类 问题。
假设特征 A 取值X ∈ X 1 , X 2 , … , X i ,每个特征概率取值 则二分类的 熵 公式如下:
图像如下
熵值法求权重过程
输入数据是已经经过预处理的数据。
熵权法求权重 分为以下几步:
- 对各特征数据进行 特征缩放 ,目的是:将数据都转换为化为无量纲数据 。
- 求各特征对应的 熵 ,目的是:求权 。
- 求各特征所对应的 权重 。
一、特征缩放
特征缩放一般有两种方法:归一化 和 标准化 。
在进行熵值法之前,如果数据方向不一致时,需要进行提前数据处理,通常为正向化或者逆向化两种处理(统称为数据归一化处理)。
归一化(正向化)
公式如下:
归一化(逆向化)
公式如下:
就是将原数据
这个区间缩放到[0,1]区间内。
缺点:当 数据发生变化(增加、删除、修改) 时,最大值和最小值 会发生变化,需要 重新计算 。
标准化
公式如下:
其中,μ 和 σ 分别代表数据的 均值 和 方差 。
二、求熵
使用上述 熵 的公式,即:
三、求权重
公式如下:
其中,k 代表 特征个数 。
这就求出了各特征对应的权重。
四、计算综合得分
熵权悖论的解释
由此可知,权重与信息熵冗余度d正相关,与信息熵e是负相关的。也就是说,方差越大,熵越小,包含的信息越多,权重应当越大。
这里与前面的结论相悖的原因就在于熵权法计算熵的公式中,p不是各取值的比例,而是各个取值的相对大小。公式不一样,结论自然不一样了。
Python实现信息熵求权重
import pandas as pd import numpy as np import math def nml(series): # 正向指标归一化 减最小值的min-max方法 l = [] for i in series: l.append((i - series.min()) / (series.max() - series.min())) return pd.Series(l, name=series.name) def nml_max(series): #负向指标归一化 l = [] for i in series: l.append((series.max() - i) / (series.max() - series.min())) return pd.Series(l, name=series.name) def nmlzt(df): #归一化函数,对正负向指标分别调用nml()和nml_max() dfn = pd.DataFrame() for i in df.columns: if (i=='D'): dfn = pd.concat([dfn, nml_max(df[i])], axis=1) else: dfn = pd.concat([dfn, nml(df[i])], axis=1) # dfn为归一化的数据 return dfn def pij(df): #求信息熵公式中的p,这里直接用取值除以取值总和,而不是数量的比例 D = df.copy() for i in range(D.shape[1]): # 列 sum = D.iloc[:, i].sum() for j in range(D.shape[0]): # 行 D.iloc[j, i] = D.iloc[j, i] / sum # 算pij return D def entropy(series): #计算信息熵 _len = len(series) def ln(x): if x > 0: return math.log(x) else: return 0 s = 0 for i in series: s += i * ln(i) return -(1 / ln(_len)) * s def _result(dfij): #求e、d、w并返回 dfn = dfij.copy() w = pd.DataFrame(index=dfn.columns, dtype='float64') l = [] for i in dfn.columns: l.append(entropy(dfn[i])) w['熵'] = l w['差异性系数'] = 1 - np.array(l) sum = w['差异性系数'].sum() l = [] for i in w['差异性系数']: l.append(i / sum) w['权重'] = l return w df = pd.read_csv('Blues_D.csv') #读取你需要计算的文件 df=df[['D','GTI']] #选取需要计算的属性列 dfn = nmlzt(df) #归一化 dfij = pij(dfn) #求p w = _result(dfij) #求权重 w.to_excel('weight_info_entropy.xlsx', sheet_name='权重')#输出结果 dfn = dfn.set_index(df.index, drop=True) print(dfn)