机器学习实战之决策树(1)---ID3算法与信息熵,基尼不纯度
2014-12-2阅读552 评论0
(1)关于ID3算法百度文库有一篇十分详细的文章,介绍看一个例子,给出了具体的计算过程。
文章链接:http://wenku.baidu.com/view/7933c2f6f61fb7360b4c65fd.html
这是最后的决策树的形状,来源是百[原]机器学习实战之决策树(1)---ID3算法与信息熵,基尼不纯度
2014-12-2阅读552 评论0
(1)关于ID3算法百度文库有一篇十分详细的文章,介绍看一个例子,给出了具体的计算过程。
文章链接:http://wenku.baidu.com/view/7933c2f6f61fb7360b4c65fd.html
这是最后的决策树的形状,来源是百度文库。
另有一篇CSDN博客介绍ID3算法:http://blog.csdn.net/zhaoyl03/article/details/8665663
基本思想:
基本思想:
角度1. 越是小型的决策树越优于大的决策树(尽管如此该算法也不是总是生成最小的树形结构)
角度2. 引入信息论中互信息(信息增益),作为判别因素的度量,即:以信息熵的下降速度作为选取测试属性的标准,所选的测试属性是从根到当前节点的路径上尚未被考虑的具有最高信息增益的属性
香农熵的公式:
p(x)是选择这个分类特征S,导致的分类情况x的概率。二分类情况x只有正负两种。
下面给出计算给定数据集计算香农熵的Python代码:
from math import log
#计算给定数据集的香农熵
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet:
currentLabel = featVec[-1]
#为所有的可能分类创建字典
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0.0
for key in labelCounts:
prob = float(labelCounts[key]) / numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt
#创建简单的数据集
def createDataSet():
dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
labels = ['no surfacint', 'flippers']
return dataSet, labels
在shell中:
>>> import trees
>>> reload(trees)
<module 'trees' from 'trees.pyc'>
>>> myDat, labels = trees.createDataSet()
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
>>> trees.calcShannonEnt(myDat)
0.9709505944546686
>>>
如果修改第一个数据,增加‘maybe’类别,熵会变大。。。(因为划分出来类多一点,更有利于降低树高度?)
>>> myDat[0][-1] = 'maybe'
>>> myDat
[[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
>>> trees.calcShannonEnt(myDat)
1.3709505944546687
或者直接加上一个分类数据,也变大,如果不多分类,但是增加一组数据,会比最开始的大。
>>> myDat.append([1, 1, 'maybe'])
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no'], [1, 1, 'maybe']]
>>> trees.calcShannonEnt(myDat)
1.4591479170272448
>>> myDat[5][-1] = 'yes'
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no'], [1, 1, 'yes']]
>>> trees.calcShannonEnt(myDat)
1.0
综上,如果分类之后,产生的新的数据集,可以划分更多的分类出来,熵增加;可以有更多的数据集包括进来,熵增加。可以按照获取最大信息熵的标准来划分数据集。
(2)基尼不纯度(来自新浪博客:http://blog.sina.com.cn/s/blog_61d2047c01018u9g.html)
基尼不纯度的大概意思是 一个随机事件变成它的对立事件的概率
例如 一个随机事件X ,P(X=0) = 0.5 ,P(X=1)=0.5
那么基尼不纯度就为 P(X=0)*(1 - P(X=0)) + P(X=1)*(1 - P(X=1)) = 0.5
一个随机事件Y ,P(Y=0) = 0.1 ,P(Y=1)=0.9
那么基尼不纯度就为P(Y=0)*(1 - P(Y=0)) + P(Y=1)*(1 - P(Y=1)) = 0.18
很明显 X比Y更混乱,因为两个都为0.5 很难判断哪个发生。而Y就确定得多,Y=0发生的概率很大。而基尼不纯度也就越小。
所以基尼不纯度也可以作为 衡量系统混乱程度的 标准度文库。
另有一篇CSDN博客介绍ID3算法:http://blog.csdn.net/zhaoyl03/article/details/8665663
基本思想:
基本思想:
角度1. 越是小型的决策树越优于大的决策树(尽管如此该算法也不是总是生成最小的树形结构)
角度2. 引入信息论中互信息(信息增益),作为判别因素的度量,即:以信息熵的下降速度作为选取测试属性的标准,所选的测试属性是从根到当前节点的路径上尚未被考虑的具有最高信息增益的属性
香农熵的公式:
p(x)是选择这个分类特征S,导致的分类情况x的概率。二分类情况x只有正负两种。
下面给出计算给定数据集计算香农熵的Python代码:
from math import log
#计算给定数据集的香农熵
def calcShannonEnt(dataSet):
numEntries = len(dataSet)
labelCounts = {}
for featVec in dataSet:
currentLabel = featVec[-1]
#为所有的可能分类创建字典
if currentLabel not in labelCounts.keys():
labelCounts[currentLabel] = 0
labelCounts[currentLabel] += 1
shannonEnt = 0.0
for key in labelCounts:
prob = float(labelCounts[key]) / numEntries
shannonEnt -= prob * log(prob, 2)
return shannonEnt
#创建简单的数据集
def createDataSet():
dataSet = [[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
labels = ['no surfacint', 'flippers']
return dataSet, labels
在shell中:
>>> import trees
>>> reload(trees)
<module 'trees' from 'trees.pyc'>
>>> myDat, labels = trees.createDataSet()
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
>>> trees.calcShannonEnt(myDat)
0.9709505944546686
>>>
如果修改第一个数据,增加‘maybe’类别,熵会变大。。。(因为划分出来类多一点,更有利于降低树高度?)
>>> myDat[0][-1] = 'maybe'
>>> myDat
[[1, 1, 'maybe'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no']]
>>> trees.calcShannonEnt(myDat)
1.3709505944546687
或者直接加上一个分类数据,也变大,如果不多分类,但是增加一组数据,会比最开始的大。
>>> myDat.append([1, 1, 'maybe'])
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no'], [1, 1, 'maybe']]
>>> trees.calcShannonEnt(myDat)
1.4591479170272448
>>> myDat[5][-1] = 'yes'
>>> myDat
[[1, 1, 'yes'], [1, 1, 'yes'], [1, 0, 'no'], [0, 1, 'no'], [0, 1, 'no'], [1, 1, 'yes']]
>>> trees.calcShannonEnt(myDat)
1.0