机器学习笔记-Decision Tree

来源:互联网 发布:淘宝培训班杭州 编辑:程序博客网 时间:2024/05/23 00:02

集成学习系列:

  • Blending and Bagging
  • Adaptive Boosting
  • Decision Tree
  • Random Forest
  • Gradient Boosted Decision Tree

Decision Tree

上一篇讲解了Adaptive Boosting算法,这个算法有两个特点:第一个是在第t轮中通过调整每一个样本点的权重值以使得在t+1轮得到不同于的gtgt+1;第二点是通过gt的表现计算一个值作为权重将其线性的融合到G中。这样的算法被证明当base learner不怎么强的时候,通过这样的方式也可以得到很强的效果。

Decision Tree Hypothesis

总结aggregation

到现在为止, 这一篇和上一篇都属于aggregation model的范畴。aggregation model简单的来说就是将g融合成G。其做法有两个主要的面向:一种称之为blending,这种是指我们已经得到了一堆的 g ,这个时候我们有三种主要的方式来对这些已经在手上的g进行融合:

  • Uniform方式:如果所有的g的重要性都是一样的, 我们可以使用uniform的方式,通过投票或者平均来进行融合,或者说给每一个g的权重都设置为1
  • Non-uniform方式:如果g的重要性是不同的, 那么可以使用non-uniform的形式来对g进行融合。这时可以将所有的g当成是一个特征转换,将进行了特征转换之后的数据丢到一个linear model里面去求解参数作为各自的重要性就可以了
  • conditional方式:如果要在不同的情形下使用不同的g,同样的我们的做法是将所有的g当成是特征转换,在two level learning的第二层的学习的时候,不再使用linear model,而是使用一个非线性的模型,这样就可以做到conditionalblending

另一种面向是我们并不知道有哪些g,我们想要一边学习g一遍将他们进行融合。目前讲了两个主要的方式:BaggingAdaBoost

  • 如果想要做uniformaggregation的话,就是用Bagging,在Bagging中,我们首先针对资料Dbootstrap来得到一些不同的资料D~t,再在这些资料的副本上得到不同的g,最后将它们uniform的融合起来。
  • 如果是要做linearaggregation的话,可以使用Adaboost,在AdaBoost中通过调整样本的权重,得到不同的g,然后linear的将它们融合起来。
  • decision tree解决的问题是要在不同的条件下使用不同的g, 并且gconditional事先不知道,需要通过学习获取的情形。

以上的内容可以总结为如下的表格:


这里写图片描述

一个决策树的示例

如下图就是一棵决策树,用于决策下班之后要不要学习在线课程。 例如,我要先看下下班的时间早不早,如果下班早的话,再看看有没有约,如果没有约的话就学习在线视频,如果有约的话就不学习了。等等。所以一个判断的过程就是从决策树的root出发来依次的判断各个决策点的条件,沿着符合条件的路径一直走到叶子节点就是决策树最终给出的决策。


这里写图片描述

一棵Decision Tree就是一个Hypothesis,就是一个函数或者说是判断的过程。我们使用G来表示,接下来看看怎么将G表示为gcondition q(x)的组合:

G(x)=t=1T qt(x)gt(x)

  • gt(x)称为base hypothesis,在这里表示的是叶子节点上的决策,这里使用的是常数,和在baggingadaboost中一样gt是组成G的部分。
  • qt(x)condition,即判断特征是否满足条件,或者是不是在某些路径path上。

或者我们从数据结构角度出发,可以通过如下的递归的方式来描述决策树:

G(x)=c=1C|[b(x)=c]|Gc(x)
,
其中,Gc(x)称为是full treeb(x)称为是分支条件,Gc(x)是条件b(x)=c时的那一棵子树。操作|[ ]|的定义如下:1=|[]|如果成立;0=|[]|如果不成立。

综合可以得到决策树的两种视角:

  • Path ViewG(x)=Tt=1|[x on path t]|leaft(x)
  • Recursive ViewG(x)=Cc=1|[b(x)=c]|Gc(x)

以上只是给出了对决策树模型的一些定义和数学上的描述,不是很重要,我们需要知道的是Decision Tree是一个非常实用的算法有很多的优点,因为该算法描述了整个做决策的过程,所有有很好的可解释性,正因为如此使得该算法在商业和医药上有很多的应用。另一个方面,该算法的很容易实现。除此之外该算法的效率也非常的高。该算法的缺点是,相对于机器学习中的其他的模型来说,该算法的理论保证很少,人们更多是使用一些设计上的技巧而不是理论上的支撑来使得算法的表现很好。

Decision Tree Algorithm

决策树算法介绍

上一小节我们介绍了Decision Tree的基本概念和表示的方法,其中说到决策树可以使用递归的方式来表示,如下:

G(x)=c=1C|[b(x)=c]|Gc(x)

通过这样的一个对决策树的递归的表示我们也可以大概的写出决策树的构造步骤。

构造Decision TreeinputD={(xn,yn)}Nn=1
if   终止条件满足
返回base hypothesis gt(x)
else
1. 从资料中找出最好的用于划分资料的特征
2. 根据以上找到的特征将资料划分为若干块 Dc,具体分为几块( c 的大小)视该特征的不同的取值的个数,或者算法具体使用的技巧而定。
3. 使用每一个 Dc 构造一个子树
4. 将所有的子树合并起来形成最后的Decision Tree, 即G(x)

通过上面的描述要想从data中学到一个决策树,有四个问题需要决定

  • 如何决定进行划分数据的特征
  • 分支的个数
  • 终止的条件
  • 满足终止条件的情况下怎么决定返回的base hypothesis

Classification and Regression Tree(CART)

CART算法是决策树算法的一种简单实现,下面我们依次谈论GART这个算法针对上面我们关心的四个问题是怎么处理的。

CART算法每次将数据划分为两份,也就是说使用该算法最后构建的决策树是一棵二叉树。CART算法最后回传的gt,也就是base hypothsis是常数,也就是叶子结点上的值是常数。如果是classification,那么叶子节点上的值就是类别;如果是regression,那么叶子节点上的值就是回归的实数值。那么怎么得到叶子节点上的这个值呢?这个返回的常数我们希望它在它所能看到的那一部分小的数据上(数据不断被划分,所以不管是维度还是个数都在不断的减少)的表现是很好的,也就是Ein是很小的, 为了做到这一点,对于分类问题来说,我们使用majority的方式决定这个常数的取值:类别最多的作为该决策叶子节点的类别;对于回归问题,最好的常数就是这一部分数据的y的平均值。

CART算法每一次会将data划分为两个子树,则另一个关心的问题是:如何划分为两个子树,即如何选择特征来对数据进行划分CART的做法是利用decision stump算法对数据进行划分,划分后计算子数据的纯度purifying。试想如果划分得到的子数据集上的样本的label都是相同的,或者说是很接近的,那么在使用一个常数作为决策树的输出的时候,得到的Ein就会很小。所以我们就是要在所有可能的Decision Stump做出的划分中,找使得impurify(D1)+impurify(D2)最小的划分,impurity(D)表示D的不纯度的大小。考虑到D1D2中数据量的差异,所以我们将上式改为|D1|impurify(D1)+|D2|impurify(D2)

Impurity

怎么衡量不纯度impurity

  • 对于regression来说,首先计算划分后的数据的所有真实值的均值y¯=average of {yn}, 不纯度的计算公式如下:
    impurity(D)=1Nn=1N(yny¯)2(1)
  • 对于classification来说,找到数据中出现次数最多的类别y,即y=majority of {yn}, 剩下的其他的类别的个数的总和就可以描述该数据集的不纯度,其中N为该数据子集的大小:
    impurity(D)=1Nn=1N|[yny]|

当有了不纯度的定义之后, 就可以在所有的decision stump的切割中,找到做好的feature来划分数据。

对于classification问题来说,另一个比较常用的衡量不纯度的指标是Gini index,定义如下:

1k=1K(Nn=1|[yn=k]|N)2

例如对于labelL={1,7,9,7,1,7,7,7,9,1}来说,Gini(L)=1((310)2+(510)2+(210)2)

CART算法做classification的时候,通常会使用Gini系数来选择划分数据集的特征;在做regression的时候, 通常使用公式(1)的计算不纯度的方法来选择划分数据集的特征。

四个基本的问题中还剩一个问题,终止条件是什么。第一种情况是当所有的y都相同的时候,这个时候无论是使用classificationGini系数还是使用regression的中的公式(1)来计算impurity得到的都是0,所以这个时候就可以终止继续构造子树,返回一个常数;第二种情况是当所有的x都相同的时候;第三种情况是是当没有特征可用的时候;这三种情况的处理是一样的, classification的话对所有的label投票, regression的话取均值。这种被迫停下来的树称为fully grown tree


CART决策树是一棵完全长成的树,叶子节点上返回的常数,对数据进行划分的依据是不纯度,每次将数据划分为两个不想交的子集。

Decision Tree Heuristics in CART

CART算法的流程

if cannot branch anymore
return gt(x)=Ein optimal constant
else

1.learn branching criteria

b(x)=argmindecision stumps h(x)c=12|Dc with h|impurity(Dc with h)

2.plit D to 2 parts Dc={(xn,yn):b(xn)=c}
3.build sub tree GcDecisionTree(Dc)
4.return G(x)=2c=1|[b(x)=c]|Gc(x)

简单总结一下CART算法的主要特点:每次分两支;通过计算纯度选择对数据进行划分的特征;返回常数值。CART算法不仅仅可以做binary classification还可以做regression, 并且只需要做一点的改变就可以很容易的处理multi classification,只需要在返回常数和计算不纯度的时候考虑多类别的问题就可以了。

加规则化因子

如果所有data的特征都不一样的时候,CART算法会得到一棵Ein为0的树(应该是这样的吧)。对于这种完全长成的树,存在较大的overfitting的风险。所以看起来我们可能需要一些regularization来控制下模型的复杂度。该算法可能会overfitting是因为划分的太过于彻底,那么是不是可以通过当划分到一定的程度的时候就不再划分,提前终止构造决策树来降低模型的复杂度呢?这个时候会得到的决策树的叶子的数量会变少,所以看来叶子的数量是一个很好的衡量决策树的复杂度的方法。
定义Ω(G)表示某个决策树G的叶子的数量,那么带有regularizer的决策树的模型如下:

Ein(G)+λΩ(G)

现在我们的目标就是要在所有的决策树中找Ein(G)+λΩ(G)最小的, 也就是说可能Ein(G)会稍微大一点, 但是复杂度小一点的决策树。这样的树称为pruned decision tree

实际操作中, 我们首先通过CART算法得到一个完全长成的树G(0),其中的上角标0表示摘除0片叶子。然后试着摘除该树中的每一片叶子, 计算得到一个在摘除一片叶子的情况下Ein最小的树G(1);然后在从这个摘掉一片叶子的树出发摘掉第二片叶子,同样找到最好的G(2)。这样就可以生成一些不同的决策树,将这些我们认为“够好”的决策树作为备选,选择一个Ein(G)+λΩ(G)最小的决策树。

Decision Tree的一些其他的特点

在实际的应用中,可能data中的信息不是数字类型(numerical features)的,而是类别类型categorical features的,例如说描述天气的情况,可能特征的取值是:晴,阴,雨,而不是数字。之前的模型对于这样的数据,像linear model等等好像不是很方便处理。但是Decision Tree可以很容易的处理这样的数据。其他的地方基本没有什么影响, 只是原来CART算法使用decision stump对数据做切分, 现在我们换成使用decision subset对数据做切分。例如对于天气的情况{晴,阴,雨}, 所有的decision subset的结果就是{{晴, (阴,雨)}{阴, (晴,雨)}{雨, (阴,晴)}}。不仅仅CART算法, 其他的大部分的Decision Tree算法都可以很轻易的处理categorical features

另外一个优点是,Decision Tree算法可以通过加入一些技巧来弥补数据缺失的问题。大致的做法是: 构造的过程中除了选择最好的特征 x 对当前的数据进行划分之外,还可以再选择一个和x能得到相似的划分效果的特征x,通常这个两个特征之间会有一个相关关系。 这样在日后使用决策树的时候,如果有一笔数据上没有特征x,那么可以使用特征x来进行替代。

CART算法的表现

针对如下的这个二元分类问题,我们来对于以下CART算法和AdaBoost算法的效果和不同之处在哪里。


这里写图片描述

以下是CART算法和AdaBoost算的结果对比, 因为在CARTAdaBoost中的base learner都使用的decision stump,所以对于二维的数据来说它们都只能做水平或者是垂直的分界线。但是从图中可以很明显看出两者之间的不同:对于AdaBoost来说,每一个decision stump的分界线都是横跨整个平面的, 但是CART却不是。因为CART算法每一个递归里面对的数据集都是缩小了的。而AdaBoost始终是在整个数据上划分。


这里写图片描述

看到这个图以及在下一个数据集上的分割线,发现自己有一个疑惑。在决策树的另一种实现算法ID3中,每次使用一种特征x进行数据的划分之后,在新的数据子集上不仅仅数据的量减少了,数据的维度也减少了。或者说每一次划分都要消耗一个特征,因为x已经用于划分数据了,所以不再考虑了。但是如果本节所讲的CART也是采用这种方式的话,怎么会在每一个点只有两个特征x,y的情况下可以做出如此多的分隔线呢?(不知道问题表述清楚了没有,希望有大神可以指教。),我想CART算法应该是不消耗特征的。

贴几个复杂的资料上的结果,加深对CARTAdaBoost算法的直观的认识。原始的资料如下:


这里写图片描述


decision stump切了10次之后。
这里写图片描述


decision stump切了20次之后。
这里写图片描述


decision stump切了30次之后。
这里写图片描述


decision stump切了90次之后。
这里写图片描述

CART在实际应用中的优点

  • 结果的可解释性
  • 可以轻易的处理多类别的分类
  • 可以应对categorical features
  • 可以解决特征缺失的问题
  • 能非常高效的得到一个非线性的模型
  • 训练和测试的效率都比较高

总结

这篇讲解了Decision Tree,从它的假设讲起,它的假设表示的就是在不同的条件下, 在不同的路径上有不同的g。决策树的构造过程是一个递归的过程,其中最重要的一步是如何划分数据,这就涉及到不纯度的计算。在CART这样的算法中有很多技巧可以使用,例如,怎么通过剪枝来做regularization,怎么处理categorical的特征,怎么应付有缺失的输入。这样的算法可以很高效的给我们一个可解释性强的非线性边界。通过这一篇和上一篇,我们已经讲解完了aggregation的基本模型,下一篇开始讲的是:当我们已经有了这些aggregation的时候,如何再将这些aggregation融合起来, 即aggregation of aggregation