python信息熵函数 python 熵值法( 七 )


10
11
12
13
14
15
16
17
18
19
20
21
输出结果为:score: 0.7335 , 即准确率有73% 。每次训练和预测的准确率分布如下:
数据离散化
然而,在上例中对特征值离散化的划分点实际上过于“野蛮”,此处介绍一种通过信息增益最大的标准来对数据进行离散化 。原理很简单,当信息增益最大时,说明用该点划分能最大程度降低数据集的不确定性 。
具体步骤如下:
对每个特征所包含的数值型特征值排序
对相邻两个特征值取均值 , 这些均值就是待选的划分点
用每一个待选点把该特征的特征值划分成两类,小于该特征点置为1 ,  大于该特征点置为0,计算此时的条件熵,并计算出信息增益
选择信息使信息增益最大的划分点进行特征离散化
实现代码如下:
def filterRawData(dataSet, colIndex, value, tag):
""" 用于把每个特征的连续值按照区分点分成两类,加入tag参数,可用于标记筛选的是哪一部分数据"""
filterDataList = []
for r in dataSet:
if (tag and r[colIndex] = value) or ((not tag) and r[colIndex]value):
newR = r[:colIndex]
newR = np.append(newR, (r[colIndex + 1:]))
filterDataList.append(newR)
return np.array(filterDataList)
def dataDiscretization(dataSet, featName):
""" 对数据每个特征的数值型特征值进行离散化 """
featureNum = dataSet.shape[1] - 1
entropy = calShannonEnt(dataSet)
for featIndex in range(featureNum):#对于每一个特征
uniqueValues = sorted(np.unique(dataSet[:, featIndex]))
meanPoint = []
for i in range(len(uniqueValues) - 1):# 求出相邻两个值的平均值
meanPoint.append(float(uniqueValues[i+1] + uniqueValues[i]) / 2.0)
bestInfoGain = 0.0
bestMeanPoint = -1
for mp in meanPoint:#对于每个划分点
subEntropy = 0.0#计算该划分点的信息熵
for tag in range(2):#分别划分为两类
subDataSet = filterRawData(dataSet, featIndex, mp, tag)
p = 1.0 * len(subDataSet) / len(dataSet)
subEntropy += p * calShannonEnt(subDataSet)
## 计算信息增益
infoGain = entropy - subEntropy
## 选择最大信息增益
if infoGain = bestInfoGain:
bestInfoGain = infoGain
bestMeanPoint = mp
featName[featIndex] = featName[featIndex] + "=" + "{:.3f}".format(bestMeanPoint)
dataSet[:, featIndex] = [1 if x = bestMeanPoint else 0 for x in dataSet[:, featIndex]]
return dataSet, featName
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
重新对数据进行离散化,并重复该步骤1000次,同时用sklearn中的DecisionTreeClassifier对相同数据进行分类,分别统计平均准确率 。运行代码如下:
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
scoreL = []
scoreL_sk = []
for i in range(1000):#对该过程进行1000次
featNames = iris.feature_names[:]
trainData, testData = https://www.04ip.com/post/train_test_split(data)#区分测试集和训练集
trainData_tmp = copy.copy(trainData)
testData_tmp = copy.copy(testData)
discritizationData,discritizationFeatName= dataDiscretization(trainData, featNames) #根据信息增益离散化
for i in range(testData.shape[1]-1):#根据测试集的区分点离散化训练集
splitPoint = float(discritizationFeatName[i].split('=')[-1])
testData[:, i] = [1 if x=splitPoint else 0 for x in testData[:, i]]

推荐阅读