算法原理
决策树模型是一种描述对实例进行分类的树形结构。其由结点(node)和有向边(directed edge)组成。结点有两种类型:内部结点(internal node)和叶结点(leaf node)。内部结点表示一个特征或属性(features),叶结点表示一个类(labels)。
用决策树对需要测试的实例进行分类:从根节点开始,对实例的某一特征进行测试,根据测试结果,将实例分配到其子结点;这时,每一个子结点对应着该特征的一个取值。如此递归地对实例进行测试并分配,直至达到叶结点。最后将实例分配到叶结点的类中。
决策树模型可以认为是 if-then 规则的集合,也可以认为是定义在特征空间与类空间上的条件概率分布。
决策树学习通常包括 3 个步骤:特征选择、决策树的生成和决策树的修剪。
决策树场景
决策树的构造
优点:计算复杂度不高,输出结果易于理解,对中间值的确实不敏感,可以处理不相关特征数据
缺点:可能会产生过度匹配问题
使用数据类型:数值型和标称型
伪代码
检测数据集中的每个子项是否属于同一分类:
if so return 类标签:
else
寻找划分数据集的最好特征
划分数据集
创建分支节点
for每个划分的子集
调用函数createBanch并增加返回结构到分支节点中
return 分支节点
一般流程
1.收集数据
2.准备数据:树构造算法只适用于标称型数据,因此数值型数据必须离散化
3.分析数据:构造树完成之后,我们应该检查图形是否符合预期
4.训练算法:构造树的数据结构
5.测试算法:使用经验树计算错误率
6.使用算法:适用于任何监督算法,决策树可以更好的理解数据的内在含义
信息增益
划分数据集的大原则:将无序的数据变得更加有序
在划分数据集之前之后的信息发生的变化称为数据增益
集合信息的度量方式称为香农熵或者熵(数据的混乱程度)
计算给定数据集的香农熵
from math import log
def clacShannonEnt(dataSet) :
numEntires = 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])/nummEntries
shannonEnt -= prob * log(prob,2)
#以2为底求对数
return shannonEnt
按照给定特征划分数据集
def splitDataSet(dataSet,axis,value):
retDataSet = []
for featVec in dataSet:
if featVec[axis] == value:
reducedFeatVec = featVec[:axis]
reducedFeatVec.extend(featVec[axis+1:])
retDataSet.append(reducedFeatVec)
return retDataSet
选择最好的数据集划分方式
def chooseBestFeatureToSplit(dataSet):
# 求第一行有多少列的 Feature, 最后一列是label列
numFeatures = len(dataSet[0]) - 1
# 数据集的原始信息熵
baseEntropy = calcShannonEnt(dataSet)
# 最优的信息增益值, 和最优的Featurn编号
bestInfoGain, bestFeature = 0.0, -1
# iterate over all the features
for i in range(numFeatures):
# 获取对应的feature下的所有数据
featList = [example[i] for example in dataSet]
# 获取剔重后的集合,使用set对list数据进行去重
uniqueVals = set(featList)
# 创建一个临时的信息熵
newEntropy = 0.0
# 遍历某一列的value集合,计算该列的信息熵
# 遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。
for value in uniqueVals:
subDataSet = splitDataSet(dataSet, i, value)
# 计算概率
prob = len(subDataSet) / float(len(dataSet))
# 计算条件熵
newEntropy += prob * calcShannonEnt(subDataSet)
# gain[信息增益]: 划分数据集前后的信息变化, 获取信息熵最大的值
# 信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。
infoGain = baseEntropy - newEntropy
print('infoGain=', infoGain, 'bestFeature=', i, baseEntropy, newEntropy)
if infoGain > bestInfoGain:
bestInfoGain = infoGain
bestFeature = i
return bestFeature