基于信息熵的数据离散化
1、准备数据
基于信息熵的数据离散化算法是由监督学习算法,在使用该方法对数据进行离散化时,需要数据有对应的标签。
下面是一份用户最近点击的20个商品的价格与是否加入购物车对应关系:
价格 标签 价格 标签 价格 标签 价格 标签
56 1 641 1 10 1 2398 1
87 1 63 0 9 0 592 1
129 0 2764 1 88 1 561 1
23 0 2323 0 222 0 764 0
342 1 453 1 97 0 121 1
对该份数据进行离散化:新建DiscreteByEntropy类,然后初始化相关函数,并加载数据。对应如下基于信息熵的数据离散化--新建类并加载数据:
import numpy as np
import math
class DiscreteByEntropy:
def __init__(self,group,threshold):
self.maxGroup = group #最大分组数
self.minInfoThreshold = threshold #停止划分的最小熵
self.result = dict() #保存划分结果
#准备数据
def loadData(self):
data = np.array(
[
[56,1],[87,1],[129,0],[23,0],[342,1],
[641,1],[63,0],[2764,1],[2323,0],[453,1],
[10,1],[9,0],[88,1],[222,0],[97,0],
]
)
return data
2、计算数据的信息熵
该步骤是计算数据的信息熵,是为下一步分割数据集做准备。对应如下基于信息熵的数据离散化--计算数据的信息熵
#计算按照数据指定数据分组后的香农熵
def calEntropy(self,data):
numData = len(data)
labelCounts = {}
for feature in data:
#获得标签
oneLabel = feature[-1]
#如果标签步骤新定义的字典里则创建该标签
labelCounts.setdefault(oneLabel,0)
#该类标签下含有数据的个数
labelCounts[oneLabel] += 1
shannonEnt = 0.0
for key in labelCounts:
#同类标签出现的概率
prob = float(labelCounts[key]) / numData
#以2为底求对数
shannonEnt -= prob * math.log(prob,2)
return shannonEnt
3、分割数据集
寻找一组数据最佳分割点的方法是:遍历所有属性值,数据按照该属性分割,使得平均熵最小。对应基于信息熵的数据离散化--分割数据集:
按照调和信息熵最小化原则分割数据集
def split(self,data):
#inf为正无穷大
minEntropy = np.inf
#记录最终分割索引
index = -1
#按照第一列对数据进行排序
sortData = data[np.argsort(data[:,0])]
#初始化最终分割数据后的熵
lastE1,lastE2 = -1,-1
#返回的数据结构,包含数据和对应的熵
S1 = dict()
S2 = dict()
for i in range(len(sortData)):
#分割数据集
splitData1,splitData2 = sortData[: i + 1],sortData[i + 1 :]
entropy1,entropy2 = (
self.calEntropy(splitData1),
self.calEntropy(splitData2),
) #计算信息熵
entropy = entropy1 * len(splitData1) / len(sortData) + \
entropy2 * len(splitData2) / len(sortData)
#如果调和平均熵小于最小值
if entropy < minEntropy:
minEntropy = entropy
index = i
lastE1 = entropy1
lastE2 = entropy2
s1["entropy"] = lastE1
s1["data"] = sortData[: index + 1]
s1["entropy"] = lastE2
s2["data"] = sortData[index + 1 :]
return S1,S2,minEntropy
4、数据离散化
按照上面基于信息熵分组的内容,对数据做离散化处理。对应基于信息熵的数据离散化--数据离散化:
#对数据进行分组
def train(self,data):
#需要遍历的key
needSplitKey = [0]
#将整个数据作为一组
self.result.setdefault(0,{})
self.result[0]["entropy"] = np.inf
self.result[0]["data"] = data
group = 1
for key in needSplitKey:
S1,S2,entropy = self.split(self.result[key]["data"])
#如果满足条件
if entropy > self.minInfoThreshold and group < self.maxGroup:
self.result[key] = S1
newKey = max(self.result.keys()) + 1
self.result[newKey] = S2
needSplitKey.extend([key])
needSplitKey.extend([newKey])
group += 1
else:
break
if __name__ == "__main__":
dbe = DiscreteByEntropy(group=6,threshold=0.5)
data = dbe.loadData()
dbe.train(data)
print("result is {}".format(dbe.result))
运行结果如下:
可见这里将商品价格分为了3份,分别为{9,10,23,56,63,87,88}、{342,453,641,2323,2764}、{97,129,222}