文章原创,最近更新:2018-08-11
本章节的主要内容是:
重点介绍项目案例1:判定鱼类和非鱼类的计算给定数据集的香农熵的函数代码
。
1.决策树项目案例介绍:
项目案例1:
判定鱼类和非鱼类
项目概述:
- 根据以下 2 个特征,将动物分成两类:鱼类和非鱼类。
- 特征: 1. 不浮出水面是否可以生存 2. 是否有脚蹼
开发流程:
- 收集数据:可以使用任何方法
- 准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
- 分析数据:可以使用任何方法,构造树完成之后,我们应该检查图形是否符合预期
- 训练算法:构造树的数据结构
- 测试算法:使用决策树执行分类
- 使用算法:此步骤可以适用于任何监督学习算法,而使用决策树可以更好地理解数据的内在含义
数据集介绍
2.计算给定数据集的香农熵的函数
这段代码主要是计算给定数据集的熵,首先创建一个名为trees.py的文件,并创建一个函数calcShannonEn()函数录入到trees.py文件.
def calcShannonEnt(dataSet):
# 获取数据集dataSet列表的长度,表示计算参与训练的数据量
numEntries=len(dataSet)
# 新建一个空字典labelCounts,用以统计每个标签出现的次数,进而计算概率
labelCounts={}
for featVec in dataSet:
# featVec[-1]获取了daatSet中每行最后一个数据,作为字典中的key(标签)
currentLabel = featVec[-1]
# 以currentLabel作为key加入到字典labelCounts.
# 如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。
# 键值存在则则对应value+1,否则为0
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel]=0
labelCounts[currentLabel] += 1
# 对于 label 标签的占比,求出 label 标签的香农熵
shannonEnt = 0.0
for key in labelCounts:
# 计算分类概率prob=标签发生频率,labelCounts[key]除以数据集长度numEntries
prob = float(labelCounts[key])/numEntries
# 计算香农熵,以2为底求对数
shannonEnt -=prob * log(prob,2)
return shannonEnt
createDataSet()函数主要是简单鱼鉴定数据集.并录入到trees.py.
测试数据集
def createDataSet():
dataSet = [[1, 1, 'yes'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
return dataSet, labels
测试代码及其结果如下:
import trees
a, b = trees.createDataSet()
trees.calcShannonEnt(a)
Out[90]: 0.9709505944546686
通过数学方式计算以上数据集的信息熵
yes | no | 总共 | |
---|---|---|---|
个数 | 2 | 3 | 5 |
比率 | \frac{2}{5} | \frac{3}{5} | 1 |
则为:
=-(\frac{2}{5}\log_{2}\frac{2}{5}+\frac{3}{5}\log_{2}\frac{3}{5})=0.97095
熵越高,则数据越混乱,这里可在数据集dataSet列表里修改第0个元素 [1, 1, 'yes']更改为[1, 1, 'maybe'],分类看下熵的变化,复制以上代码运行下:
def createDataSet():
dataSet = [[1, 1, 'maybe'],
[1, 1, 'yes'],
[1, 0, 'no'],
[0, 1, 'no'],
[0, 1, 'no']]
labels = ['no surfacing','flippers']
return dataSet, labels
测试代码及其结果如下:
import trees
a, b = trees.createDataSet()
trees.calcShannonEnt(a)
Out[97]: 1.3709505944546687
通过数学方式计算以上数据集的信息熵
maybe | yes | no | 总共 | |
---|---|---|---|---|
个数 | 1 | 1 | 3 | 5 |
比率 | \frac{1}{5} | \frac{1}{5} | \frac{3}{5} | 1 |
则为:
=-(\frac{1}{5}\log_{2}\frac{1}{5}+\frac{1}{5}\log_{2}\frac{1}{5}+\frac{3}{5}\log_{2}\frac{3}{5})=1.37095
3.相关知识点
3.1香农熵(又名信息熵)
香农熵如果要用平民语言说得尽可能直白的话,可以认为是信息的杂乱程度的量化描述。具体公式如下:
H(x)=-\sum_{i=1}^{n}p(x_{i})\log_{2}P(x_{i}),i=1,2,...,n
其中,x可以当成一个向量,就是若干个xi产生的概率乘以该可能性的信息量,然后各项做加和。
备注:在其他资料上会看到这里的log是取10的对数lg,或者自然常数e的ln自然对数。这里强调一下,在应用的过程中用任何一种值做底都是可以的,但是注意在某一次应用的整个过程中,参与本次应用的所有香农熵都必须采用同一个底,不能将不同底的对数求出的熵再做加和或者比较,这样完全没有意义(就好像3米和2英尺,虽然都是长度单位,但是3米+2英尺既得不到5米也得不到5英尺)。
案例1:2选1“一边倒”
假设中国乒乓球队和巴西乒乓球队历史交手共64次,其中中国获胜63次,63/64是赛前普遍认可的中国队获胜的概率——注意,这个是先验概率。中国乒乓球队和巴西乒乓球队比赛的结果的香农熵约为
中国 | 巴西 | 总共 | |
---|---|---|---|
获胜次数 | 63 | 1 | 64 |
比率 | \frac{63}{64} | \frac{1}{64} | 1 |
H(x)=-(\frac{63}{64}\log_{2}\frac{63}{64}+\frac{1}{64}\log_{2}\frac{1}{64})=0.1164
总结:
对于无限不循环小数只能根据需要取一个近似值,注意这是一个“2选1的情况,并且确定性相当高”的事件的熵。
案例2:2选1“差不多”
再看一个两者势均力敌的例子,假设德国乒乓球队和法国乒乓球队比赛,双方历史交手64次,交手胜负为32:32,那么1/2是赛前普遍认可的德国队的获胜概率,同时也是法国队的获胜概率。德国乒乓球队和法国乒乓球队比赛的结果的香农熵约为
中国 | 巴西 | 总共 | |
---|---|---|---|
获胜次数 | 32 | 32 | 64 |
比率 | \frac{1}{2} | \frac{1}{2} | 1 |
H(x)=-(\frac{1}{2}\log_{2}\frac{1}{2}+\frac{1}{2}\log_{2}\frac{1}{2})=1
案例3:32选1“差不多”
如果在足球世界杯决赛阶段,即假设32支球队获得冠军等概率的情况下进行香农熵的计算。(一共32个)
队伍1 | 队伍2 | 队伍i | 队伍32 | 总共 | |
---|---|---|---|---|---|
获胜次数 | 1 | 1 | ... | 1 | 32 |
比率 | \frac{1}{32} | \frac{1}{32} | ... | \frac{1}{32} | 1 |
H(x)=-(\frac{1}{32}\log_{2}\frac{1}{32}+\frac{1}{32}\log_{2}\frac{1}{32}+...\frac{1}{32}\log_{2}\frac{1}{32})=5
案例4:32选1“一边倒”
假设队伍1获胜概率为99%,而其他31支队伍每一支队伍的获胜概率都为1%/31,求比赛结果的香农熵为多少。(一共32个)
队伍1 | 队伍2 | 队伍i | 队伍32 | 总共 | |
---|---|---|---|---|---|
比率 | 0.99 | 0.01/31 | ... | 0.01/31 | 1 |
H(x)=-(0.99log_{2}0.99+0.01log_{2}\frac{0.01}{31}+...0.01log_{2}\frac{0.01}{31}=0.130
结论:
- 在信息可能有N种情况时,如果每种情况出现的概率相等,那么N越大,香农熵越大。
- 在信息可能有N种情况时,当N一定,那么其中所有情况概率相等时香农熵是最大的,而如果有一种情况的概率比其他情况的概率都大很多,那么香农熵就会越小。
具体的值在具体情况可以进行量化的计算比较。笼统地说就是:
信息越确定,越单一,香农熵越小;
信息越不确定,越混乱,香农熵越大。