决策树原理
- 决策树(decision tree):是一种基本的分类与回归方法,此处主要讨论分类的决策树。在分类问题中,表示基于特征对实例进行分类的过程,可以认为是if-then的集合,也可以认为是定义在特征空间与类空间上的条件概率分布。
- 用决策树分类:从根节点开始,对实例的某一特征进行测试,根据测试结果将实例分配到其子节点,此时每个子节点对应着该特征的一个取值,如此递归的对实例进行测试并分配,直到到达叶节点,最后将实例分到叶节点的类中。
决策树基本知识
- 决策树学习的目标:根据给定的训练数据集构建一个决策树模型,使它能够对实例进行正确的分类。
- 决策树学习的本质:从训练集中归纳出一组分类规则,或者说是由训练数据集估计条件概率模型。
- 决策树学习的损失函数:正则化的极大似然函数。
- 决策树学习的测试:最小化损失函数。
- 决策树学习的目标:在损失函数的意义下,选择最优决策树的问题。
- 决策树原理和问答猜测结果游戏相似,根据一系列数据,然后给出游戏的答案。
决策树的构造
决策树通常有三个步骤:特征选择、决策树的生成、决策树的修剪。
-
第一步:如何切分特征(选择节点)–特征选择
问题:根节点的选择该用哪个特征呢?接下来呢?如何切分呢?
目标:通过一种衡量标准,来计算通过不同特征进行分支选择后的分类情况,找出来最好的那个当成根节点,以此类推。
衡量标准-熵、GINI系数(不纯度)
熵:熵是表示随机变量不确定性的度量
解释:说白了就是物体内部的混乱程度,比如杂货市场里面什么都有那肯定混乱呀,专卖店里面只卖一个牌子的那就稳定多啦如何决策一个节点的选择呢?(如何确定一个分裂是最好的)
特征挑选方法(信息增益法)
选择具有最高信息增益的特征作为测试特征,利用该特征对节点样本进行划分子集,会使得各子集中不同类别样本的混合程度最低,在各子集中对样本划分所需的信息(熵)最少,信息增益既可以用熵也可以用GINI系数来计算。具体实现方式下面介绍。
-
第二步:决策树的生成(基础版)
-
从根节点出发,根节点包括所有的训练样本。
-
一个节点(包括根节点),若节点内所有样本均属于同一类别,那么将该节点就成为叶节点,并将该节点标记为样本个数最多的类别。
-
否则利用采用信息增益法来选择用于对样本进行划分的特征,该特征即为测试特征,特征的每一个值都对应着从该节点产生的一个分支及被划分的一个子集。在决策树中,所有的特征均为符号值,即离散值。如果某个特征的值为连续值,那么需要先将其离散化。
-
递归上述划分子集及产生叶节点的过程,这样每一个子集都会产生一个决策(子)树,直到所有节点变成叶节点。
递归操作的停止条件就是:
(1)一个节点中所有的样本均为同一类别,那么产生叶节点
(2)没有特征可以用来对该节点样本进行划分,这里用attribute_list=null为表示。此时也强制产生叶节点,该节点的类别为样本个数最多的类别
(3)没有样本能满足剩余特征的取值,即test_attribute= 对应的样本为空。此时也强制产生叶节点,该节点的类别为样本个数最多的类别。
-
第三步:决策树剪枝
由于噪声等因素的影响,会使得样本某些特征的取值与样本自身的类别不相匹配的情况,基于这些数据生成的决策树的某些枝叶会产生一些错误;尤其是在决策树靠近枝叶的末端,由于样本变少,这种无关因素的干扰就会突显出来;由此产生的决策树可能存在过拟合的现象。树枝修剪就是通过统计学的方法删除不可靠的分支,使得整个决策树的分类速度和分类精度得到提高。
1.为什么要剪枝:决策树过拟合风险很大,理论上可以完全分得开数据
(想象一下,如果树足够庞大,每个叶子节点不就一个数据了嘛)
2 剪枝策略:预剪枝,后剪枝树枝修剪包括预剪枝和后剪枝两种方法:
(1)预剪枝:边建立决策树边进行剪枝的操作(更实用)
在决策树生成分支的过程,除了要进行基础规则的判断外,还需要利用统计学的方法对即将分支的节点进行判断,比如统计χ2或统计信息增益,如果分支后使得子集的样本统计特性不满足规定的阈值,则停止分支;但是阈值如何选取才合理是比较困难的。(2)后剪枝:当建立完决策树后来进行剪枝操作
在决策树充分生长后,修剪掉多余的分支。根据每个分支的分类错误率及每个分支的权重,计算该节点不修剪时预期分类错误率;对于每个非叶节点,计算该节点被修剪后的分类错误率,如果修剪后分类错误率变大,即放弃修剪;否则将该节点强制为叶节点,并标记类别。产生一系列修剪过的决策树候选之后,利用测试数据(未参与建模的数据)对各候选决策树的分类准确性进行评价,保留分类错误率最小的决策树。
决策树的三种常用算法
为什么同一种决策树,能有三种呢,很自然就能想到,是不是前面的算法,有些缺陷,后面在对这些缺陷做了改进,提出的一种新的算法呢。
1, 决策树之ID3算法/基本决策树
ID3算法的核心是在决策树各个结点上对应信息增益准则选择特征,递归地构建决策树。
具体方法是:
1)从根结点(root node)开始,对结点计算所有可能的特征的信息增益,选择信息增益最大的特征作为结点的特征。
2)由该特征的不同取值建立子节点,再对子结点递归地调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止;
3)最后得到一个决策树。
ID3相当于用极大似然法进行概率模型的选择
2, 决策树之C4.5算法
C4.5算法与ID3算法决策树的生成过程相似,C4.5算法对ID3算法进行了改进。它是用信息增益率(比)来 选择特征。
这里的改进主要是针对样本特征来作。
(1)基本决策树要求特征A取值为离散值,如果A是连续值,假如A有v个取值,则对特征A的测试可以看成是对v-1个可能条件的测试,其实可以把这个过程看成是离散化的过程,只不过这种离散的值间隙会相对小一点;当然也可以采用其他方法,比如将连续值按段进行划分,然后设置亚变量;
(2)特征A的每个取值都会产生一个分支,有的时候会导致划分出来的子集样本量过小,统计特征不充分而停止继续分支,这样在强制标记类别的时候也会带来局部的错误。针对这种情况可以采用A的一组取值作为分支条件;或者采用二元决策树,每一个分支代表一个特征取值的情况(只有是否两种取值)。
(3)某些样本在特征A上值缺失,针对这种空值的情况,可以采用很多方法,比如用其他样本中特征A出现最多的值来填补空缺,比如采用均值、中值等,甚至在某些领域的数据中可以采用样本内部的平滑来补值,当样本量很大的时候也可以丢弃这些有缺失值的样本。
(4)随着数据集的不断减小,子集的样本量会越来越小,所构造出的决策树就可能出现碎片、重复、复制等总是。这时可以利用样本的原有特征构造新的特征进行建模;
(5)信息增益法会倾向于选择取值比较多的特征(这是信息熵的定义决定了的),针对这一问题,人们提出了增益比率法(gain ratio),将每个特征取值的概率考虑在内,及gini索引法,χ2χ2条件统计表法和G统计法等。
3, CART分类树建立算法的具体流程
算法输入是训练集D,基尼系数的阈值,样本个数阈值。
输出是决策树T。
我们的算法从根节点开始,用训练集递归的建立CART树。
1) 对于当前节点的数据集为D,如果样本个数小于阈值或者没有特征,则返回决策子树,当前节点停止递归。
2) 计算样本集D的基尼系数,如果基尼系数小于阈值,则返回决策树子树,当前节点停止递归。
3) 计算当前节点现有的各个特征的各个特征值对数据集D的基尼系数,对于离散值和连续值的处理方法和基尼系数的计算见第二节。缺失值的处理方法和上篇的C4.5算法里描述的相同。
4) 在计算出来的各个特征的各个特征值对数据集D的基尼系数中,选择基尼系数最小的特征A和对应的特征值a。根据这个最优特征和最优特征值,把数据集划分成两部分D1和D2,同时建立当前节点的左右节点,做节点的数据集D为D1,右节点的数据集D为D2。(注:注意是二叉树,故这里的D1和D2是有集合关系的,D2=D-D1)
5) 对左右的子节点递归的调用1-4步,生成决策树。
代码实现
from math import log
import operator
"""
函数说明:计算给定数据集的经验熵(香农熵)
Parameters:
dataSet:数据集
Returns:
shannonEnt:经验熵
Modify:
2018-03-12
"""
def calcShannonEnt(dataSet):
#返回数据集行数
numEntries=len(dataSet)
#保存每个标签(label)出现次数的字典
labelCounts={
}
#对每组特征向量进行统计
for featVec in dataSet:
currentLabel=featVec[-1] #提取标签信息
if currentLabel not in labelCounts.keys