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))
输出结果为:
补充:
信息增益比(增益率)
基尼指数