1、熵、条件熵与信息增益
(1)熵(entropy)
(2)条件熵(conditional entropy)
(3)信息增益(information gain)
2、信息增益算法实现流程
2、数据集以及每个特征信息增益的计算
2.1贷款申请样本数据表
表5.1 贷款申请样本数据表
|
1 |
青年 |
否 |
否 |
一般 |
否 |
|
2 |
青年 |
否 |
否 |
好 |
否 |
|
3 |
青年 |
是 |
否 |
好 |
是 |
|
4 |
青年 |
是 |
是 |
一般 |
是 |
|
5 |
青年 |
否 |
否 |
一般 |
否 |
|
6 |
中年 |
否 |
否 |
一般 |
否 |
|
7 |
中年 |
否 |
否 |
好 |
否 |
|
8 |
中年 |
是 |
是 |
好 |
是 |
|
9 |
中年 |
否 |
是 |
非常好 |
是 |
|
10 |
中年 |
否 |
是 |
非常好 |
是 |
|
11 |
老年 |
否 |
是 |
非常好 |
是 |
|
12 |
老年 |
否 |
是 |
好 |
是 |
|
13 |
老年 |
是 |
否 |
好 |
是 |
|
14 |
老年 |
是 |
否 |
非常好 |
是 |
|
15 |
老年 |
否 |
否 |
一般 |
否 |
2.2根据信息增益准则选择最优特征
3、Python3实现熵与信息增益选择最优特征
在编写代码之前,我们先对数据集进行属性标注。
- 年龄:0代表青年,1代表中年,2代表老年;
- 有工作:0代表否,1代表是;
- 有自己的房子:0代表否,1代表是;
- 信贷情况:0代表一般,1代表好,2代表非常好;
- 类别(是否给贷款):no代表否,yes代表是。
代码实现如下:
-
# -*- coding: UTF-8 -*- -
from math import log -
""" -
函数说明:创建测试数据集 -
""" -
def createDataSet(): -
dataSet = [[0, 0, 0, 0, 'no'], #数据集 -
[0, 0, 0, 1, 'no'], -
[0, 1, 0, 1, 'yes'], -
[0, 1, 1, 0, 'yes'], -
[0, 0, 0, 0, 'no'], -
[1, 0, 0, 0, 'no'], -
[1, 0, 0, 1, 'no'], -
[1, 1, 1, 1, 'yes'], -
[1, 0, 1, 2, 'yes'], -
[1, 0, 1, 2, 'yes'], -
[2, 0, 1, 2, 'yes'], -
[2, 0, 1, 1, 'yes'], -
[2, 1, 0, 1, 'yes'], -
[2, 1, 0, 2, 'yes'], -
[2, 0, 0, 0, 'no']] -
labels = ['年龄', '有工作', '有自己的房子', '信贷情况'] #分类属性 -
return dataSet, labels #返回数据集和分类属性 -
""" -
函数说明:计算给定数据集的经验熵(香农熵) -
Parameters: -
dataSet - 数据集 -
Returns: -
shannonEnt - 经验熵(香农熵) -
""" -
def calcShannonEnt(dataSet): -
numEntires = len(dataSet) #返回数据集的行数 -
labelCounts = {} #保存每个标签(Label)出现次数的字典 -
for featVec in dataSet: #对每组特征向量进行统计 -
currentLabel = featVec[-1] #提取标签(Label)信息 -
if currentLabel not in labelCounts.keys(): #如果标签(Label)没有放入统计次数的字典,添加进去 -
labelCounts[currentLabel] = 0 -
labelCounts[currentLabel] += 1 #Label计数 -
shannonEnt = 0.0 #经验熵(香农熵) -
for key in labelCounts: #计算香农熵 -
prob = float(labelCounts[key]) / numEntires #选择该标签(Label)的概率 -
shannonEnt -= prob * log(prob, 2) #利用公式计算 -
return shannonEnt #返回经验熵(香农熵) -
""" -
函数说明:按照给定特征划分数据集 -
Parameters: -
dataSet - 待划分的数据集 -
axis - 划分数据集的特征 -
value - 需要返回的特征的值 -
""" -
def splitDataSet(dataSet, axis, value): -
retDataSet = [] #创建返回的数据集列表 -
for featVec in dataSet: #遍历数据集 -
if featVec[axis] == value: -
reducedFeatVec = featVec[:axis] #去掉axis特征 -
reducedFeatVec.extend(featVec[axis+1:]) #将符合条件的添加到返回的数据集 -
retDataSet.append(reducedFeatVec) -
return retDataSet #返回划分后的数据集 -
""" -
函数说明:选择最优特征 -
Parameters: -
dataSet - 数据集 -
Returns: -
bestFeature - 信息增益最大的(最优)特征的索引值 -
""" -
def chooseBestFeatureToSplit(dataSet): -
numFeatures = len(dataSet[0]) - 1 #特征数量 -
baseEntropy = calcShannonEnt(dataSet) #计算数据集的香农熵 -
bestInfoGain = 0.0 #信息增益 -
bestFeature = -1 #最优特征的索引值 -
for i in range(numFeatures): #遍历所有特征 -
#获取dataSet的第i个所有特征 -
featList = [example[i] for example in dataSet] -
uniqueVals = set(featList) #创建set集合{},元素不可重复 -
newEntropy = 0.0 #经验条件熵 -
for value in uniqueVals: #计算信息增益 -
subDataSet = splitDataSet(dataSet, i, value) #subDataSet划分后的子集 -
prob = len(subDataSet) / float(len(dataSet)) #计算子集的概率 -
newEntropy += prob * calcShannonEnt(subDataSet) #根据公式计算经验条件熵 -
infoGain = baseEntropy - newEntropy #信息增益 -
print("第%d个特征的增益为%.3f" % (i, infoGain)) #打印每个特征的信息增益 -
if (infoGain > bestInfoGain): #计算信息增益 -
bestInfoGain = infoGain #更新信息增益,找到最大的信息增益 -
bestFeature = i #记录信息增益最大的特征的索引值 -
return bestFeature #返回信息增益最大的特征的索引值 -
if __name__ == '__main__': -
dataSet, features = createDataSet() -
entropy=calcShannonEnt(dataSet) -
bestfeature=chooseBestFeatureToSplit(dataSet) -
print("训练集的熵为:%f"%(entropy)) -
print("最优特征索引值:" + str(bestfeature))
输出结果为:
补充:
信息增益比(增益率)
基尼指数