分类算法-决策树

决策树理论
在决策树理论中,有这样一句话,“用较少的东西,照样可以做很好的事情。越是小的决策树,越优于大的决策树”。数据分类是一个两阶段过程,包括模型学习阶段(构建分类模型)和分类预测阶段(使用模型预测给定数据的类标号)。决策树分类算法属于监督学习(Supervised learning),即样本数据中有类别标号。下面是两个阶段的简单描述:

决策树步骤

第一阶段(以分类为例),可以看做是根据样本来学习一个映射或函数y=f(x)表达式,能够使用它预测给定元组X的类标号y。

第二阶段,使用第一阶段学习得到的模型进行分类。首先评估分类器的预测准确率。这个过程要尽量减少过拟合(为什么是尽量减少?因为过拟合是避免不了的,再好的模型也会有过拟合的情况的)。

简介

决策树归纳是从有类标号的训练元组中学习决策模型。常用的决策树算法有ID3,C4.5和CART。它们都是采用贪心(即非回溯的)方法,自顶向下递归的分治方法构造。

这几个算法选择属性划分的方法各不相同,ID3使用的是信息增益,C4.5使用的是信息增益率,而CART使用的是Gini基尼指数。下面来简单介绍下决策树的理论知识。内容包含熵、信息增益、信息增益率以及Gini指数的概念及公式。

决策树划分方式

二元划分和多元划分;如果采用二元划分,对于离散变量而言,选定property分类即可;对于连续变量,需要选定split_point。

算法优点

算法比较简单;
理论易于理解;
对噪声数据有很好的健壮性。

目前,决策树是应用最为广泛的归纳推理算法之一,在数据挖掘中受到研究者的广泛关注。衍生出很多出色的集成算法,如random forest、adaboost、gradient tree boosting都是基于决策树的模型。

算法流程

收集数据:任意方法和途径。
准备数据:书构造算法只适用于标称型数据,因此数据必须离散化。
分析数据:构造树完成后,检查图形是否符合预测。
训练算法:决策树的数据构造。
测试算法:一般将决策树用于分类,可以用错误率衡量,而错误率使用经验率计算。
使用算法:决策树可以用于任何监督学习算法。

基于信息论的三种决策树算法

划分数据集的最大原则是:使无序的数据变的有序。如果一个训练数据中有20个特征,那么选取哪个做划分依据?这就必须采用量化的方法来判断,量化划分方法有多重,其中一项就是“信息论度量信息分类”。基于信息论的决策树算法有ID3、CART和C4.5等算法,其中C4.5和CART两种算法从ID3算法中衍生而来。

CART和C4.5支持数据特征为连续分布时的处理,主要通过使用二元切分来处理连续型变量,即求一个特定的值-分裂值:特征值大于分裂值就走左子树,或者就走右子树。这个分裂值的选取的原则是使得划分后的子树中的“混乱程度”降低,具体到C4.5和CART算法则有不同的定义方式。

ID3算法由Ross Quinlan发明,建立在“奥卡姆剃刀”的基础上:越是小型的决策树越优于大的决策树(be simple简单理论)。

ID3算法中根据信息论的信息增益评估和选择特征,每次选择信息增益最大的特征做判断模块。ID3算法可用于划分标称型数据集,没有剪枝的过程,为了去除过度数据匹配的问题,可通过裁剪合并相邻的无法产生大量信息增益的叶子节点(例如设置信息增益阀值)。使用信息增益的话其实是有一个缺点,那就是它偏向于具有大量值的属性–就是说在训练集中,某个属性所取的不同值的个数越多,那么越有可能拿它来作为分裂属性,而这样做有时候是没有意义的,另外ID3不能处理连续分布的数据特征,于是就有了C4.5算法。CART算法也支持连续分布的数据特征。

C4.5是ID3的一个改进算法,继承了ID3算法的优点。C4.5算法用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足在树构造过程中进行剪枝;能够完成对连续属性的离散化处理;能够对不完整数据进行处理。C4.5算法产生的分类规则易于理解、准确率较高;但效率低,因树构造过程中,需要对数据集进行多次的顺序扫描和排序。也是因为必须多次数据集扫描,C4.5只适合于能够驻留于内存的数据集。

CART算法的全称是Classification And Regression Tree,采用的是Gini指数(选Gini指数最小的特征s)作为分裂标准,同时它也是包含后剪枝操作。ID3算法和C4.5算法虽然在对训练样本集的学习中可以尽可能多地挖掘信息,但其生成的决策树分支较大,规模较大。为了简化决策树的规模,提高生成决策树的效率,就出现了根据GINI系数来选择测试属性的决策树算法CART。

ID3:信息增益作为划分属性

熵被用来衡量一个随机变量出现的期望值。熵越大,一个变量的不确定性就越大(也就是可取的值很多),把它搞清楚所需要的信息量也就越大,熵是整个系统的平均消息量。

信息熵是信息论中用于度量信息量的一个概念。一个系统越是有序,信息熵就越低;反之,一个系统越是混乱,信息熵就越高。所以,信息熵也可以说是系统有序化程度的一个度量。

熵(Entropy)的计算公式
熵定义为信息的期望值。先看看信息的定义:
$$l(x_i)=−log_2p(x_i)$$
对D中的元组所有分类所有可能值的信息期望,即熵,计算公式如下:
$$Entropy=H(D)=E(I(D))=−∑_i^np_ilog_2(p_i)$$,$$p_i$$是D中任意元组属于类$$C_i$$非零概率。

一个属性的信息增益越大,表明属性对样本的熵减少的能力就更强,该属性使得数据所属类别的不确定性变为确定性的能力越强。

信息增益在统计学中称为互信息,互信息是条件概率与后验概率的比值,化简之后就可以得到信息增益。所以说互信息其实就是信息增益。计算方法【互信息=熵-条件熵】。熵描述的是不确定性。

熵越大,不确定性就越大,条件熵$H(B|A)$描述的是在A给定的条件下B的不确定性,如果条件熵越小,表示不确定性就越小,那么B就越容易确定结果。所以使用熵减去条件熵,就得到了信息增益,他描述的不确定性的降低程度,可以用来度量两个变量的相关性。比如,在给定一个变量的条件下,另一个变量它的不确定性能够降低多少,如果不确定性降低得越多,那么它的确定性就越大,就越容易区分,两者就越相关。注:期望信息越小,分区的纯度越高。

首先计算特征A对数据集D的经验条件熵$H(D|A)$,在数学上就是条件概率分布(Condition Probability).

$H(D|A)=∑_j|Dj||D|×H(D_j)$,项$|Di||D|$充当第j个分区的权重
引入条件熵,在信息论中主要是为了消除结果的不确定性。然后计算信息增益:
$Gain(A)=H(D)−H(D|A)$
$Gain(A)$即为所求的信息增益。
在决策树中,ID3属性划分标准使用的是信息增益,C4.5使用的是信息增益率。

C4.5算法继承了ID3算法的优点,并在以下几方面对ID3算法进行了改进:

  • 用信息增益率来选择属性,克服了用信息增益选择属性时偏向选择取值多的属性的不足;
  • 在树构造过程中进行剪枝;
  • 能够完成对连续属性的离散化处理;
  • 能够对不完整数据进行处理。

C4.5算法有如下优点:产生的分类规则易于理解,准确率较高。其缺点是:在构造树的过程中,需要对数据集进行多次的顺序扫描和排序,因而导致算法的低效。另外,C4.5只适合于能够驻留于内存的数据集,当训练集大得无法在内存容纳时程序无法运行。

另外,无论是ID3还是C4.5最好在小数据集上使用,决策树分类一般只试用于小数据。当属性取值很多时最好选择C4.5算法,ID3得出的效果会非常差,因为使用信息增益划分时它倾向于取值多的属性。

计算信息增益率时,用到了分裂信息计算公式:
$SplitH(D|A)=−∑|Dj||D|×log_2(|Dj||D|)$

信息增益率定义为:
$GainRate(A)=Gain(A)SplitH(D|A)$
选择具有最大增益率的特征作为分裂特征。

3.基尼指数Gini index

基尼指数主要在CART算法中用到,随机森林中用到的属性划分标准也是它。Gini index划分是二元的,它度量的是数据分区或训练元组集D的不纯度,表示的是一个随机选中的样本在子集中被分错的可能性。计算方式如下:
$Gini(D)=1−∑p_i$,其中,$p_i$是D中元组数以$C_i$类的概率,对m个类计算和。
Gini指数越大,不纯度越大,越不容易区分。当考虑二元划分裂时,计算每个结果分区的不纯度加权和。比如A有两个值,则特征D被划分成D1和D2,这时Gini指数为:
$$Gini_A(D) = \frac{D_1}{D} Gini(D_1) + \frac{D_2}{D} Gini(D_2)$$

上面的式子表示的是不确定性的大小。对于每个属性,考虑每种可能的二元划分,对于离散值属性,选择该属性产生最小Gini指数的自己作为它的分裂信息。

连续型数据的处理

先把连续属性转换为离散属性再进行处理。虽然本质上属性的取值是连续的,但对于有限的采样数据它是离散的,如果有N条样本,那么我们有N-1种离散化的方法:<=vj的分到左子树,>vj的分到右子树。计算这N-1种情况下最大的信息增益率。

另外,对于连续属性先进行排序(升序),只有在决策属性(即分类发生了变化)发生改变的地方才需要切开,这可以显著减少运算量。经证明,在决定连续特征的分界点时采用增益这个指标(因为若采用增益率,splittedinfo影响分裂点信息度量准确性,若某分界点恰好将连续特征分成数目相等的两部分时其抑制作用最大),而选择属性的时候才使用增益率这个指标能选择出最佳分类特征。

在C4.5中,对连续属性的处理如下:

  1.  对特征的取值进行升序排序
    
  2.  两个特征取值之间的中点作为可能的分裂点,将数据集分成两部分,计算每个可能的分裂点的信息增益(InforGain)。优化算法就是只计算分类属性发生改变的那些特征取值。
    
  3.  选择修正后信息增益(InforGain)最大的分裂点作为该特征的最佳分裂点
    
  4.  计算最佳分裂点的信息增益率(Gain Ratio)作为特征的Gain Ratio。注意,此处需对最佳分裂点的信息增益进行修正:减去$$\frac{log_2(N-1)}{|D|}$$(N是连续特征的取值个数,D是训练数据数目,此修正的原因在于:当离散属性和连续属性并存时,C4.5算法倾向于选择连续特征做最佳树分裂点)
    

实现连续特征数据集划分的Python程序为:

def binSplitDataSet(dataSet, feature, value):
    mat0 = dataSet[nonzero(dataSet[:,feature] > value)[0],:][0]    
    mat1 = dataSet[nonzero(dataSet[:,feature] <= value)[0],:][0]    
    return mat0,mat1

其中dataset为numpy matrix, feature为dataset连续特征在dataset所有特征中的index,value即为feature临近两值的均值。

叶子裁剪

决策树为什么要剪枝?原因就是避免决策树“过拟合”样本。前面的算法生成的决策树非常的详细而庞大,每个属性都被详细地加以考虑,决策树的树叶节点所覆盖的训练样本都是“纯”的。因此用这个决策树来对训练样本进行分类的话,你会发现对于训练样本而言,这个树表现堪称完美,它可以100%完美正确得对训练样本集中的样本进行分类(因为决策树本身就是100%完美拟合训练样本的产物)。但是,这会带来一个问题,如果训练样本中包含了一些错误,按照前面的算法,这些错误也会100%一点不留得被决策树学习了,这就是“过拟合”。C4.5的缔造者昆兰教授很早就发现了这个问题,他作过一个试验,在某一个数据集中,过拟合的决策树的错误率比一个经过简化了的决策树的错误率要高。那么现在的问题就来了,如何在原生的过拟合决策树的基础上,通过剪枝生成一个简化了的决策树?

检测和减去这些分支的过程被称为树剪枝。树剪枝方法用于处理过分适应数据问题。通常,这种方法使用统计度量,减去最不可靠的分支,这将导致较快的分类,提高树独立于训练数据正确分类的能力。

决策树常用的剪枝常用的简直方法有两种:预剪枝(Pre-Pruning)和后剪枝(Post-Pruning)。预剪枝是根据一些原则及早的停止树增长,如树的深度达到用户所要的深度、节点中样本个数少于用户指定个数、不纯度指标下降的最大幅度小于用户指定的幅度等。预剪枝的核心问题是如何事先指定树的最大深度,如果设置的最大深度不恰当,那么将会导致过于限制树的生长,使决策树的表达式规则趋于一般,不能更好地对新数据集进行分类和预测。除了事先限定决策树的最大深度之外,还有另外一个方法来实现预剪枝操作,那就是采用检验技术对当前结点对应的样本集合进行检验,如果该样本集合的样本数量已小于事先指定的最小允许值,那么停止该结点的继续生长,并将该结点变为叶子结点,否则可以继续扩展该结点。

后剪枝则是通过在完全生长的树上剪去分枝实现的,通过删除节点的分支来剪去树节点,可以使用的后剪枝方法有多种,比如:代价复杂性剪枝、最小误差剪枝、悲观误差剪枝等等。后剪枝操作是一个边修剪边检验的过程,一般规则标准是:在决策树的不断剪枝操作过程中,将原样本集合或新数据集合作为测试数据,检验决策树对测试数据的预测精度,并计算出相应的错误率,如果剪掉某个子树后的决策树对测试数据的预测精度或其他测度不降低,那么剪掉该子树。

1、第一种方法,也是最简单的方法,称之为基于误判的剪枝。这个思路很直接,完全的决策树不是过度拟合么,我再搞一个测试数据集来纠正它。对于完全决策树中的每一个非叶子节点的子树,我们尝试着把它替换成一个叶子节点,该叶子节点的类别我们用子树所覆盖训练样本中存在最多的那个类来代替,这样就产生了一个简化决策树,然后比较这两个决策树在测试数据集中的表现,如果简化决策树在测试数据集中的错误比较少,并且该子树里面没有包含另外一个具有类似特性的子树(所谓类似的特性,指的就是把子树替换成叶子节点后,其测试数据集误判率降低的特性),那么该子树就可以替换成叶子节点。该算法以bottom-up的方式遍历所有的子树,直至没有任何子树可以替换使得测试数据集的表现得以改进时,算法就可以终止。

2、第一种方法很直接,但是需要一个额外的测试数据集,能不能不要这个额外的数据集呢?为了解决这个问题,于是就提出了悲观剪枝。该方法剪枝的依据是训练样本集中的样本误判率。我们知道一颗分类树的每个节点都覆盖了一个样本集,根据算法这些被覆盖的样本集往往都有一定的误判率,因为如果节点覆盖的样本集的个数小于一定的阈值,那么这个节点就会变成叶子节点,所以叶子节点会有一定的误判率。而每个节点都会包含至少一个的叶子节点,所以每个节点也都会有一定的误判率。悲观剪枝就是递归得估算每个内部节点所覆盖样本节点的误判率。剪枝后该内部节点会变成一个叶子节点,该叶子节点的类别为原内部节点的最优叶子节点所决定。然后比较剪枝前后该节点的错误率来决定是否进行剪枝。该方法和前面提到的第一种方法思路是一致的,不同之处在于如何估计剪枝前分类树内部节点的错误率。

缺失值处理

对于某些采样数据,可能会缺少属性值。在这种情况下,处理缺少属性值的通常做法是赋予该属性的常见值,或者属性均值。另外一种比较好的方法是为该属性的每个可能值赋予一个概率,即将该属性以概率形式赋值。例如给定Boolean属性B,已知采样数据有12个B=0和88个B=1实例,那么在赋值过程中,B属性的缺失值被赋为B(0)=0.12、B(1)=0.88;所以属性B的缺失值以12%概率被分到False的分支,以88%概率被分到True的分支。这种处理的目的是计算信息增益,使得这种属性值缺失的样本也能处理。

相对于那些离散值属性,分类树算法倾向于选择那些连续值属性,因为连续值属性会有更多的分支,熵增益也最大。算法需要克服这种倾向,我们利用增益率来克服这种倾向。增益率也可以用来克服连续值属性倾向。增益率作为选择属性的依据克服连续值属性倾向,这是没有问题的。但是如果利用增益率来选择连续值属性的分界点,会导致一些副作用。分界点将样本分成两个部分,这两个部分的样本个数之比也会影响增益率。根据增益率公式,我们可以发现,当分界点能够把样本分成数量相等的两个子集时(我们称此时的分界点为等分分界点),增益率的抑制会被最大化,因此等分分界点被过分抑制了。子集样本个数能够影响分界点,显然不合理。因此在决定分界点是还是采用增益这个指标,而选择属性的时候才使用增益率这个指标。这个改进能够很好得抑制连续值属性的倾向。当然还有其它方法也可以抑制这种倾向,比如MDL。

i)当开始决定选择哪个属性用来进行分支时,如果有些训练样本缺失了某些属性值时该怎么办?
ii)一个属性已被选择,那么在决定分支的时候如果有些样本缺失了该属性该如何处理?
iii)当决策树已经生成,但待分类的样本缺失了某些属性,这些属性该如何处理?针对这三个问题,昆兰提出了一系列解决的思路和方法。

对于问题i),计算属性a的增益或者增益率时,如果有些样本没有属性a,那么可以有这么几种处理方式:

(1)忽略这些缺失属性a的样本。
(2)给缺失属性a的样本赋予属性a一个均值或者最常用的的值。
(3)计算增益或者增益率时根据缺失属性样本个数所占的比率对增益/增益率进行相应的“打折”。
(4)根据其他未知的属性想办法把这些样本缺失的属性补全。

对于问题ii),当属性a已经被选择,该对样本进行分支的时候,如果有些样本缺失了属性a,那么:
(1)忽略这些样本。
(2)把这些样本的属性a赋予一个均值或者最常出现的值,然后再对他们进行处理。
(3)把这些属性缺失样本,按照具有属性a的样本被划分成的子集样本个数的相对比率,分配到各个子集中去。至于哪些缺失的样本被划分到子集1,哪些被划分到子集2,这个没有一定的准则,可以随机而动。(A)把属性缺失样本分配给所有的子集,也就是说每个子集都有这些属性缺失样本。
(3)单独为属性缺失的样本划分一个分支子集。
(4)对于缺失属性a的样本,尝试着根据其他属性给他分配一个属性a的值,然后继续处理将其划分到相应的子集。

对于问题iii),对于一个缺失属性a的待分类样本,有这么几种选择:

(1)如果有单独的确实分支,依据此分支。
(2)把待分类的样本的属性a值分配一个最常出现的a的属性值,然后进行分支预测。
(3)根据其他属性为该待分类样本填充一个属性a值,然后进行分支处理。
(4)在决策树中属性a节点的分支上,遍历属性a节点的所有分支,探索可能所有的分类结果,然后把这些分类结果结合起来一起考虑,按照概率决定一个分类。
(5)待分类样本在到达属性a节点时就终止分类,然后根据此时a节点所覆盖的叶子节点类别状况为其分配一个发生概率最高的类。

[参考内容](http://blog.csdn.net/u011067360/article/details/21861989

CART
在数据挖掘中,决策树主要有两种类型:

  • 分类树 的输出是样本的类标
  • 回归树 的输出是一个实数(例如房子的价格,病人呆在医院的时间等)。

术语分类和回归树 (CART) 包含了上述两种决策树, 最先由Breiman 等提出.分类树和回归树有些共同点和不同点—例如处理在何处分裂的问题。分类回归树(CART,Classification And Regression Tree)也属于一种决策树,结构为二叉树。

CART-Tree 的特点

  • CART中用于选择变量的不纯性度量是Gini指数;
  • 如果目标变量是标称的,并且是具有两个以上的类别,则CART可能考虑将目标类别合并成两个超类别(双化);
  • 如果目标变量是连续的,则CART算法找出一组基于树的回归方程来预测目标变量。

1、从根节点t=1开始,从所有可能候选S集合中搜索使不纯性降低最大的划分S,然后,使用划分S将节点1(t=1)划分成两个节点t=2和t=3;
2、在t=2和t=3上分别重复划分搜索过程。

基尼不纯度指标

在CART算法中, 基尼不纯度表示一个随机选中的样本在子集中被分错的可能性。基尼不纯度为这个样本被选中的概率乘以它被分错的概率。当一个节点中所有样本都是一个类时,基尼不纯度为零。

剪枝

其实剪枝的准则是如何确定决策树的规模,可以参考的剪枝思路有以下几个:
1:使用训练集合(Training Set)和验证集合(Validation Set),来评估剪枝方法在修剪结点上的效用

2:使用所有的训练集合进行训练,但是用统计测试来估计修剪特定结点是否会改善训练集合外的数据的评估性能,如使用Chi-Square(Quinlan,1986)测试来进一步扩展结点是否能改善整个分类数据的性能,还是仅仅改善了当前训练集合数据上的性能。

3:使用明确的标准来衡量训练样例和决策树的复杂度,当编码长度最小时,停止树增长,如MDL(Minimum Description Length)准则。

1、Reduced-Error Pruning(REP,错误率降低剪枝)
该剪枝方法考虑将书上的每个节点作为修剪的候选对象,决定是否修剪这个结点有如下步骤组成:
1:删除以此结点为根的子树
2:使其成为叶子结点
3:赋予该结点关联的训练数据的最常见分类
4:当修剪后的树对于验证集合的性能不会比原来的树差时,才真正删除该结点
因为训练集合的过拟合,使得验证集合数据能够对其进行修正,反复进行上面的操作,从底向上的处理结点,删除那些能够最大限度的提高验证集合的精度的结点,直到进一步修剪有害为止(有害是指修剪会减低验证集合的精度)
REP是最简单的后剪枝方法之一,不过在数据量比较少的情况下,REP方法趋于过拟合而较少使用。这是因为训练数据集合中的特性在剪枝过程中被忽略,所以在验证数据集合比训练数据集合小的多时,要注意这个问题。
尽管REP有这个缺点,不过REP仍然作为一种基准来评价其它剪枝算法的性能。它对于两阶段决策树学习方法的优点和缺点提供了了一个很好的学习思路。由于验证集合没有参与决策树的创建,所以用REP剪枝后的决策树对于测试样例的偏差要好很多,能够解决一定程度的过拟合问题。

2、Pessimistic Error Pruning(PEP,悲观剪枝)
先计算规则在它应用的训练样例上的精度,然后假定此估计精度为二项式分布,并计算它的标准差。对于给定的置信区间,采用下界估计作为规则性能的度量。这样做的结果,是对于大的数据集合,该剪枝策略能够非常接近观察精度,随着数据集合的减小,离观察精度越来越远。该剪枝方法尽管不是统计有效的,但是在实践中有效。
PEP为了提高对测试集合的预测可靠性,PEP对误差估计增加了连续性校正(Continuity Correction)
PEP算法是唯一使用Top-Down剪枝策略,这种策略会导致与先剪枝出现同样的问题,将该结点的某子节点不需要被剪枝时被剪掉;另外PEP方法会有剪枝失败的情况出现。
虽然PEP方法存在一些局限性,但是在实际应用中表现出了较高的精度,。两外PEP方法不需要分离训练集合和验证机和,对于数据量比较少的情况比较有利。再者其剪枝策略比其它方法相比效率更高,速度更快。因为在剪枝过程中,树中的每颗子树最多需要访问一次,在最坏的情况下,它的计算时间复杂度也只和非剪枝树的非叶子节点数目成线性关系。

Cost-Complexity Pruning(CCP、代价复杂度)
CCP方法包含两个步骤:
1:从原始决策树T0开始生成一个子树序列{T0、T1、T2、...、Tn},其中Ti+1是从Ti总产生,Tn为根节点
2:从子树序列中,根据树的真实误差估计选择最佳决策树。
剪枝过程特别重要,所以在最优决策树生成过程中占有重要地位。有研究表明,剪枝过程的重要性要比树生成过程更为重要,对于不同的划分标准生成的最大树(Maximum Tree),在剪枝之后都能够保留最重要的属性划分,差别不大。反而是剪枝方法对于最优树的生成更为关键。

推荐阅读更多精彩内容