目录
1. 决策树基本概念
决策树就是一棵树,可解释性强,可用if-then规则解释,易让人理解。决策树的生成是一个递归的过程,一颗决策树包含一个根节点、若干个内部结点和若干个叶结点;叶结点对应于决策结果,其他每个结点则对应于一个属性测试;每个结点包含的样本集合根据属性测试的结果被划分到子结点中;根结点包含样本全集,从根结点到每个叶子结点的路径对应了一个判定测试序列。下图是以买电脑为例构造的决策树。
2. 决策树类别
- ID3决策树:用信息增益来判断当前节点应该用什么特征来构建决策树。选择信息增最高的进行划分,容易偏向于取值较多的特征
- C4.5决策树:用的是增益率,容易偏向于取值较少的特征
- CART决策树:分类和回归都能做,基尼系数越小越好
3. 构建决策树
3.1 选择最优特征
再讲选择最优特征前先补充我们需要用到的信息熵和信息增益,这二个也是进行最优特征选取的关键所在。
3.1.1 信息熵
决策树学习的关键在于如何选择最优特征进行划分,这时候就要用到信息增益,什么是信息增益呢?在划分数据集之前之后信息发生的变化成为信息增益,知道如何计算信息增益,我们就可以计算每个特征值划分数据集获得的信息增益,获得信息增益最高的特征就是最好的选择。先来看看信息熵(information entropy)的定义:假如当前样本集D中第k类样本所占的比例为, 为类别的总数(对于二元分类来说,k=2)。则样本集的信息熵为:
信息熵的相关代码如下:
# -*- coding: UTF-8 -*-
from math import log
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 #返回信息熵
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 #返回数据集和分类属性
if __name__ == '__main__':
dataSet, features = createDataSet()
print(dataSet)
print(calcShannonEnt(dataSet))
代码运行结果如下图所示,代码是先打印训练数据集,然后打印计算的信息熵H(D):
3.1.2 信息增益
最优特征的选取需要看信息增益,信息增益是相对于特征而言的,信息增益越大,特征对最终的分类结果影响也就越大,我们就应该选择对最终分类结果影响最大的那个特征作为我们的分类特征,就是选择信息增益最大的属性。假定属性a有 V个可能的取值,如果使用特征 a来对数据集D进行划分,则会产生V个分支结点, 其中第v(小v)个结点包含了数据集D中所有在特征a上取值为的样本总数,记为。因此可以根据上面信息熵的公式计算出信息熵,再考虑到不同的分支结点所包含的样本数量不同,给分支节点赋予权重,即样本数越多的分支节点的影响越大,因此,能够计算出特征a对样本集D进行划分所获得的“信息增益”: