一. 前言
本篇博文主要对决策树算法做一个总结。主要内容包括,ID3算法和C4.5算法的简单介绍、CART算法的重点介绍和决策树是如何剪枝的,以及决策树的优缺点和决策树在sklearn中使用的一些技巧。
决策树是一种基本的分类与回归方法。它的预测结果容易理解,易于向业务部门解释,预测速度快,可以处理类别型(离散型)数据和数值型(连续型)数据。决策树学习通常包括3个步骤:特征选择、决策树的生成和决策树的修剪。这些决策树学习的思想主要来源于由Quinlan在1986年提出的ID3算法和1993年提出的C4.5算法,以及Breiman等人在1984年提出的CART(Classification and Regression Tree)算法。
二. 决策树算法介绍
2.1 ID3算法介绍
在介绍ID3算法之前介绍一下什么是信息熵以及信息增益。
2.1.1 熵介绍
熵是信息论中的概念,熵度量了事物的不确定性,越不确定的事物,它的熵就越大。当每件事物发生的概率相同时,它们发生的随机性最大,所以它们的熵也就越大。随机变量X的熵(也称为经验熵)表达式如下:
其中n代表X的n种不同的离散取值。而代表了X取值为i的概率,log是以2或e为底的对数。
下面是两个变量X,Y的联合熵表达式:
下面是条件熵的表达式:
H(X)度量了X的不确定性,条件熵H(X|Y)度量了我们在知道Y以后X剩下的不确定性,而度量了X在知道Y以后不确定性减少程度,这个度量在信息论中称为互信息,记为:
,在决策树算法中叫做信息增益。ID3算法就是用信息增益来判别当前节点应该用什么特征来构建决策树。某个特征的信息增益越大表示该特征对数据集的分类的不确定性减少的程度越高,越适合用来分类。
2.1.2 信息增益的算法
输入:训练集D和特征A
输出:特征A对训练数据集D的信息增益
(1)计算数据集D的经验熵H(D),表示第k个类别的的样本个数
(2)计算特征A对数据集D的经验条件熵
(3)计算信息增益
2.1.3 ID3算法
ID3算法的核心是在决策树各个节点上应用信息增益准则选择特征,递归地构建决策树。具体方法是:从根节点开始,对节点计算所有可能的特征的信息增益,选择信息增益最大的特征作为节点的特征,由该特征的不同取值建立子节点;再对子节点递归的调用以上方法,构建决策树;直到所有特征的信息增益均很小或没有特征可以选择为止。最后得到一个决策树。ID3相当于用极大似然估计法进行概率模型的选择。
ID3算法描述:
输入:训练数据集D,特征集A,阈值;
输出:决策树T
(1)若D中所有实例属于同一类,则T为单节点树,并将类
作为该节点的类标记,返回T;
(2)若,则T为单节点树,并将D中实例数最大的类
作为该节点的类标记,返回T;
(3)否则,按信息增益算法计算A中个特征对D的信息增益,选择信息增益最大的特征;
(4)若果的信息增益小于阈值
,则置T为单节点树,并将D中实例数最大的类
作为该节点的类标记,返回T;
(5)否则,对的每一个可能值
,依
将D分割为若干非空子集
,将
中实例数最大的类作为标记,构建子节点,由节点及其子节点构成树T,返回T;
(6)对第i个子节点,以为训练集,以
为特征集,递归地调用(1)~(5)步,得到子树
,返回
.
2.1.4 ID3算法的不足
(1)ID3没有考虑连续特征,比如长度,密度都是连续值,无法在ID3运用。这大大限制了ID3的用途;
(2)ID3采用信息增益大的特征优先建立决策树的节点。缺点是在相同条件下,取值比较多的特征比取值少的特征信息增益大。比如一个变量有2个值,各为1/2,另一个变量为3个值,各为1/3,其实他们都是完全不确定的变量,但是取3个值的比取2个值的信息增益大;
(3)ID3算法对于缺失值的情况没有做考虑;
(4)没有考虑过拟合的问题。
对于上述的改进Quinlan提出了C4.5算法,下面就介绍一下C4.5算法。
2.2 C4.5算法介绍
在介绍C4.5算法之前介绍一下什么是信息增益比。上面提到,以信息增益作为划分训练数据集的特征,存在偏向于选择取值较多的特征的问题。使用信息增益比可以对这一问题进行校正。
2.2.1 信息增益比
特征A对训练数据集D的信息增益比为,定义为其信息增益
与训练数据集D关于特征A的值的熵
之比,即:
其中,,n是特征A类别个数,
表示取第i个类别的样本个数,
为样本个数。
2.2.2 C4.5算法
C4.5算法与ID3算法相似,C4.5算法对ID3算法进行了改进,C4.5在生成的过程中,用信息增益比来选择特征。
C4.5算法描述:
输入:训练数据集D,特征集A,阈值;
输出:决策树T.
(1)若D中所有实例属于同一类,则T为单节点树,并将类
作为该节点的类标记,返回T;
(2)若,则T为单节点树,并将D中实例数最大的类
作为该节点的类标记,返回T;
(3)否则,按信息增益比来计算A中个特征对D的信息增益比,选择信息增益比最大的特征;
(4)若果的信息增益比小于阈值
,则置T为单节点树,并将D中实例数最大的类
作为该节点的类标记,返回T;
(5)否则,对的每一个可能值
,依
将D分割为若干非空子集
,将
中实例数最大的类作为标记,构建子节点,由节点及其子节点构成树T,返回T;
(6)对第i个子节点,以为训练集,以
为特征集,递归地调用(1)~(5)步,得到子树
,返回
.
2.2.3 C4.5算法的不足
(1)C4.5引入了正则化系数进行初步的剪枝,但是剪枝的效果不够好;
(2)C4.5生成的是多叉树(ID3算法生成的也是多叉树),即一个父节点可以有多个子节点。很多时候,在计算机中二叉树模型会比多叉树运算效率高。如果采用二叉树,可以提高效率;
(3)C4.5只能用于分类,不能应用于回归,这也大大的限制了它的用途;
(4)C4.5由于使用了熵模型,里面有大量的耗时的对数运算,如果是连续值还有大量的排序运算。如果能够加以模型简化可以减少运算强度但又不牺牲太多准确性的话,那就更好了。
上面的4个问题在CART树中进行了部分的改进。下面我们将介绍CART决策树算法。
2.3. CART算法介绍
2.3.1 CART介绍
CART(Classification And Regression Tree),即可以用作分类也可以用作回归,相较于ID3算法和C4.5算法,CART算法的用途更加广泛。sklearn中的决策树就是使用CART算法构建的。
CART是在给定输入随机变量X条件下输出随机变量Y的条件概率分布的学习方法。CART构建决策树用的是二叉树结构,在每个叶节点上预测的是概率分布,也就是在输入给定的条件下输出的条件概率分布。
CART算法由以下两步组成:
(1)决策树生成:基于训练数据集生成决策树,生成的决策树要尽量大;
(2)决策树剪枝:用验证集对已生成的树进行剪枝并选择最优子树,这时用损失函数最小作为剪枝的标准。
CART决策树的生成就是递归的调用二叉树的过程。对回归树用平方误差最小化准则(mse)或绝对误差最小化准则(mae),对分类树用基尼指数最小化准则,进行特征选择,生成二叉树。
2.3.2 回归树生成(使用均方误差)
对于连续型数据,使用回归树进行预测。在训练数据集所在的输入空间中,递归地将每个区域划分为两个子区域并决定每个子区域上的输出值,构建二叉树。
输入:训练数据集D
输出:回归树
(1)选择最优切分变量j与切分点s,求解:
遍历变量j,对固定的切分变量j扫描切分点s,选择使上式达到最小值的对;
(2)用选定的对划分区域并决定相应的输出值:
,
,
其中,由式子可以看出,为节点m中样本的平均值。
(3)继续对两个子区域调用步骤(1),(2),直到满足停止条件;
(4)将输入空间划分为M个区域,生成决策树:
即,当使用样本进行预测时,样本最终落入的叶节点的均值作为最终的预测值。
2.3.3 分类树生成(使用基尼指数)
对于离散型数据使用分类树进行预测。分类树基尼指数选择最优的特征,同时决定该特征的最优二值切分点。
基尼指数的介绍:在分类问题中,假设有K个类,样本点属于第k类的概率为,则概率分布的基尼指数定义为:
对于给定样本集合D,其基尼指数为:
其中,是D中属于第k类的样本子集,K是类别的个数。
如果,样本集合D根据特征A是否取某一可能值a被分割成两部分,即:
,
则在特征A的条件下,集合D的基尼指数为:
基尼指数Gini(D)表示集合D的不确定性,基尼指数Gini(D,A)表示经A=a分割后集合D的不确定性。基尼指数值越大,样本集合的不确定性也就越大,这与熵相似。
分类树算法介绍:
输入:训练数据集D,停止计算条件;
输出:CART决策树;
根据训练数据集,从根节点开始,递归地对每个节点进行以下操作,构建二叉决策树
(1)计算节点内特征对数据集的基尼指数。此时对每一个特征A,对其可能取的每个值a,根据样本点对A=a的测试为“是”或”否“将D分割成和
两个部分,计算A=a时的基尼指数;
(2)在所有可能的特征A以及它们所有可能的切分点a中,选择基尼指数最小的特征及其对应的切分点作为最优特征与最优切分点。依最优特征与最优切分点,从现节点生成两个子节点,将训练数据集依特征分配到两个子节点中去;
(3)对两个子节点递归地调用(1),(2),直到满足停止条件(停止计算的条件是节点中的样本个数小于预定阈值,或样本集的基尼指数小于预定阈值,即样本基本属于同一类,或者没有更多特征);
(4)生成CART决策树。
三. CART树剪枝
由于决策树算法很容易对训练集过拟合,从而导致泛化能力差,为了解决这个问题,我们需要对CART树进行剪枝,即类似于线性回归的正则化,来增加决策树的泛化能力。CART采用的办法是后剪枝法,即先生成决策树,然后产生所有可能的剪枝后的CART树,最后使用交叉验证来检验各种剪枝的效果,选择泛化能力最好的剪枝策略。
也就是说,CART树的剪枝算法可以概括为两步,第一步是从原始决策树生成各种剪枝效果的决策树,第二部是用交叉验证来检验剪枝后的预测能力,选择泛化预测能力最好的剪枝后的树作为最终的CART树。
首先我们看看剪枝的损失函数度量,在剪枝的过程中,对于任意的一刻子树T,其损失函数为:
其中,为正则化参数,这和线性回归的正则化一样。
为训练数据的预测误差,分类树是用基尼系数度量,回归树是均方差度量。
是子树T的叶子节点的数量。
当时,即没有正则化,原始的生成的CART树即为最优子树。当
时,即正则化强度达到最大,此时由原始的生成的CART树的根节点组成的单节点树为最优子树。当然,这是两种极端情况。一般来说,
越大,则剪枝剪的越厉害,生成的最优子树相比原生决策树就越偏小。对于固定的
,一定存在使损失函数
最小的唯一子树。
看过剪枝的损失函数度量后,我们再来看看剪枝的思路,对于位于节点t的任意一颗子树,如果没有剪枝,它的损失是:
如果将其剪掉,仅仅保留根节点,则损失是:
当或者
很小时,
,当
增大到一定的程度时:
当继续增大时不等式反向,也就是说,如果满足下式:
和
有相同的损失函数,但是
节点更少,因此可以对子树
进行剪枝,也就是将它的子节点全部剪掉,变为一个叶子节点
。
最后我们看看CART树的交叉验证策略。上面我们讲到,可以计算出每个子树是否剪枝的阈值,如果我们把所有的节点是否剪枝的值
都计算出来,然后分别针对不同的
所对应的剪枝后的最优子树做交叉验证。这样就可以选择一个最好的
,有了这个
,我们就可以用对应的最优子树作为最终结果。
好了,有了上面的思路,我们现在来看看CART树的剪枝算法。
输入:CART树建立算法得到的原始决策树。
输出:最优决策子树。
算法过程如下:
(1)初始化, 最优子树集合
;
(2)从叶子节点开始自下而上计算各内部节点t的训练误差损失函数(回归树为均方差,分类树为基尼系数), 叶子节点数
,以及正则化阈值
,更新
(3)得到所有节点的值的集合M。
(4)从M中选择最大的值,自上而下的访问子树t的内部节点,如果
时,进行剪枝。并决定叶节点t的值。如果是分类树,则是概率最高的类别,如果是回归树,则是所有样本输出的均值。这样得到
对应的最优子树
(5)最优子树集合,
;
(6)如果M不为空,则回到步骤4。否则就已经得到了所有的可选最优子树集合;
(7)采用交叉验证在选择最优子树
.
四. 决策树算法优缺点
优点:
(1)决策树很容易理解和解释,而且决策树也容易可视化(在sklearn中可以使用export_graphviz包进行决策树可视化);
(2)基本不需要预处理,不需要提前归一化,处理缺失值;
(3)决策树在预测时的时间代价是O(logN),其中N是预测的样本集大小;
(4)能够处理数值型(连续型)和类别型(离散型)的数据。很多其他技术通常在分析数据集的时候只专注于其中一点,即要么是数值型,要么是类别型;
(5)能够处理多维度输出的分类问题,即我们的预测值有多个维度,且多维度是相关的;
(6)决策树使用是作为一个白盒,相较于黑盒的神经网络,决策树在逻辑上可以得到很好的解释;
(7)可以交叉验证的剪枝来选择模型,从而提高泛化能力;
(8)对异常点的容错能力好,健壮性强。
缺点:
(1)决策树容易过拟合,导致模型的泛化能力很差。可以通过剪枝(目前sklearn中的决策树不支持剪枝,所以需要我们自己设置,如叶节点最小值,树的最大深度等),设置每个叶子节点的最小样本数和树的最大深度来避免这个问题;
(2)决策树不稳定,一些很小的变化可能会导致完全不同的决策树生成。这个问题可以通过集成方法来缓解(如:随机森林);
(3)学习一棵最优化的决策树是NPC问题,因此实际中的决策树学习算法是基于启发式的算法,例如贪心算法在局部做到最优化决策树的每个节点,这样的方法并不能保证能得到一个全局最优的决策树。这个问题可以通过集成的方法来得到改善;
(4)一些复杂的关系决策树很难去学,因为决策树并不能清楚的表达它们,比如,异或问题,多路复用问题等。一般这种关系可以换神经网络分类方法来解决;
(5)如果某些类别的样本比例过大,生成决策树容易偏向于这些类别。因此建议在创建决策树之前要平衡数据集。
五. 决策树ID3,C4.5和CART比较
算法 | 支持模型 | 树结构 | 特征选择 | 连续值处理 | 缺失值处理 | 剪枝 |
ID3 | 分类 | 多叉树 | 信息增益 | 不支持 | 不支持 | 不支持 |
C4.5 | 分类 | 多叉树 | 信息增益比 | 支持 | 支持 | 支持 |
CART | 分类,回归 | 二叉树 | 基尼系数,均方差 | 支持 | 支持 | 支持 |
六. 决策树在sklearn中的一些建议
(1)当数据的特征维度很高而数据量又很少的时候,这样的数据在构建决策树的时候往往会过拟合。所以我们要控制样本数量和特征的之间正确的比率;
(2)在构建决策树之前,可以考虑预先执行降维技术(如PCA,ICA或特征选择),以使我们生成的树更有可能找到具有辨别力的特征;
(3)在训练一棵树的时候,可以先设置max_depth=3来将树可视化出来,以便我们找到树是怎样拟合我们数据的感觉,然后在增加我们树的深度;
(4)树每增加一层,填充所需的样本数量是原来的2倍,比如我们设置了最小叶节点的样本数量,当我们的树层数增加一层的时候,所需的样本数量就会翻倍,所以我们要控制好树的最大深度,防止过拟合;
(5)使用min_samples_split(节点可以切分时拥有的最小样本数)
和 min_samples_leaf(最小叶节点数)
来控制叶节点的样本数量。这两个值设置的很小通常意味着我们的树过拟合了,而设置的很大意味着我们树预测的精度又会降低。通常设置min_samples_leaf=5
;
(6)当树的类比不平衡的时候,在训练之前一定要先平很数据集,防止一些类别大的类主宰了决策树。可以通过采样的方法将各个类别的样本数量到大致相等,或者最好是将每个类的样本权重之和(sample_weight)规范化为相同的值。另请注意,基于权重的预剪枝标准(如min_weight_fraction_leaf)将比不知道样本权重的标准(如min_samples_leaf)更少偏向主导类别。
(7)如果样本是带权重的,使用基于权重的预剪枝标准将更简单的去优化树结构,如mn_weight_fraction_leaf,这确保了叶节点至少包含了样本权值总体总和的一小部分;
(8)在sklearn中所有决策树使用的数据都是np.float32类型的内部数组。如果训练数据不是这种格式,则将复制数据集,这样会浪费计算机资源。
(9)如果输入矩阵X非常稀疏,建议在调用fit函数和稀疏csr_matrix之前转换为稀疏csc_matrix,然后再调用predict。 当特征在大多数样本中具有零值时,与密集矩阵相比,稀疏矩阵输入的训练时间可以快几个数量级。
七. 参考文献/博文
(1)《统计学习方法》第五章决策树
(2)sklearn官方网站
(3)一篇比较好的博客