决策树的进化(ID3、C4.5、CART、GBDT、RF、DART、lambdaMART、XGBoost、lightGBM)

pipeline

在数据挖掘领域中,决策树是对数据进行建模的一种很有效的手段。当数据集被清洗好后,数据集就是样本的集合,每一个样本都是有一样多的属性,但属性值可能不同(也有可能不存在即属性值缺失)。每一个样本,分为属性(也可称为特征)和label两部分,我们运用决策树处理数据就是为了从样本的这些属性里面找出规则,来建立模型可以去预测样本中label,而样本中的原label我们称之为ground truth,与预测的label按一定的方式进行计算得出损失值,通过减小该损失值来优化模型。


决策树

决策树首先是一棵树,树含有一个根结点、若干个内部结点及若干个叶结点。这样的一棵树其实就对应了一种决策规则,对于新的样本,我们根据它的属性,从根结点向下开始逐步进行属性测试,最终叶结点对应决策结果。下面来说说具体的建树过程:

给定输入训练集,训练集中每一个样本含x和y,x就是样本的属性部分,y就是label,A是x中所含属性的集合。举个例子,假定某数据集用来记录人体体质是否达标的,那么用到的指标(属性)可以是身高、体重、年龄,A={身高,体重,年龄},D中的x可以是(180,64,25)(这就是属性值),y可以是达标或不达标(可以用布尔变量0,1表示)。

从上图可以看出,决策树算法是一个递归的过程。首先生成第一个结点,该结点为根结点,包含所有的样本和所有的属性,直接对结点进行递归边界测试,一是看该结点所包含的样本是不是都属于同一个label,是就直接返回,该结点作为叶结点,该label就是该叶结点的预测label。如果不是第一种情况,那么再看属性集是不是为空,或者该结点所包含的所有样本是不是在属性集上都属于同一个label,是则返回,否则的话就要选取最优属性进行划分。假定按照某种方式选取到最优属性a,那么再根据a的属性值(离散或者连续)对当前结点进行划分,划分过后生成多个分支,每一个分支都是a属性的取值情况,也包含了对应该取值情况的样本子集。之后,我们再对样本子集及剩下的属性集进行递归处理,最终我们就得到一颗决策树。

通俗点讲,就是给定一个集合和一些判断点,把集合按照这些判断点用if-else-elif的形式不断进行划分,当到达递归边界时就停止划分,并给出叶结点的预测label。那么我们所建立的决策树模型实际上就是一个庞大的if-else语句的块,在新样本到来时,我们还是根据新样本的所有属性的属性值情况,用if-else对它不断进行判别,最终流到叶结点,该叶结点的预测label就是新样本的预测label,我们得到的决策树就是类似if-else-elif的语句块。


ID3(Iterative Dichotomiser)

在上文中描述的某种方式就是本节所要讨论的内容,也就是最优属性的选择问题。首先我们来解决为什么要选取最优属性的问题,然后解决如何选取最优属性的问题。

在对训练集进行划分后,得到的进一步的模型是要比未划分的模型更准确,因为划分之后结点的纯度(样本子集中属于同一label的比例)就会提高,这样就能提高预测新样本的准确率。但是我们是想要得到最优的属性,然后将样本集合按照这个属性划分时,纯度的提升会更多些。

对于纯度的提升大小,我们可以用信息增益来表示,那么选择最优属性其实就是选择使得信息增益最大的那个属性。而某属性的信息增益是由按照该属性划分前后的信息熵之间的差表示的,信息熵定义为:

D是样本集合,|y|是label种类的个数,y是label的种类集合,pk是当前样本集合D中第k类样本所占的比例。

那么信息增益的计算就可以由下面的公式来表示:

被减数就是划分前的信息熵,减数则是按某属性划分后的各分支下的信息熵之和,那么两个值相减就得到了信息增益。信息熵衡量了当前数据集的混乱程度,信息熵越大则说明混乱程度越大,纯度越低。但我们是想要纯度越低越好,那么也就是减数越小越好,这样也就对应了信息增益越大越好。

ID3就是以信息增益为指标来选取最优划分属性的,但是仍有不足。也就是,它倾向于选取取值数目多的属性,因为这样的属性计算出来的信息增益最大,但往往会导致泛化能力变弱。比如样本集有100个样本,然后样本有一个编号属性,100个样本的编号各不相同,如果按编号属性划分则对新样本的预测很不友好,因为编号对label的影响太小了。

基于此,下面就有C4.5的最优属性选取方式就减轻了信息增益的倾向带来的不足。


C4.5

C4.5采用增益率来选取最优属性,也就是在ID3提出的信息增益下面加一个分母,这个分母就是用来惩罚取值数目过多的属性。以下就是增益率的定义:

IV(a)称为属性a的固有值,如果属性a的取值数目过多,那么IV(a)会变得很大,那么增益率就会变得很小。但是C4.5并不是单纯地选取增益率最大的属性作为最优属性,而是先比较信息增益,也就是说我们在信息增益高于平均水平的属性集合中再选取增益率最大的属性。


CART(Classification and Regression Tree)

CART决策树使用基尼指数来衡量数据集的纯度,基尼指数越小,数据集的纯度就越高,可以基尼指数类比为信息熵。但事实上,基尼指数是反映从数据集中随机抽取两个样本,label不一致的概率。对于这个概率,我们希望它越小越好,这样数据集的纯度就越高。基尼指数的定义如下:

类比4.2公式的减数的形式,我们可以得到属性a的基尼指数定义为:

根据上式,我们依次计算各属性的基尼指数,然后将基尼指数最小的属性作为最优属性。


GBDT(MART、GBRT、GBM)

上文叙述的ID3、C4.5、CART的内容主要是针对分类树最优属性的选取方法的介绍,从这节开始介绍针对回归树最优属性的选取方法以及怎样从决策树本身的模型改进。

GBDT(梯度提升树)是由Boosting Tree(提升树)改进而来,直接先摆上提升树的算法伪码:

我们知道一棵树的预测结果是由树的叶子结点给出的,提升树的预测结果是一系列回归树的预测结果之和。那么构建提升树就由构建第一颗回归树开始,先初始化提升树模型f0(x)=0,也就是该提升树对所有的x的预测label都是0。然后计算残差,也就是用ground truth减去预测label,拟合得到的新数据集(x,r)就得到第一棵回归树T。

回归树的生成其实与前文所述的分类树的生成相似,不同之处在于选取最优属性的优化目标不同。分类树的优化目标就是信息增益,增益率以及基尼指数等,而回归树的优化目标(这里用的损失函数是MSE)如下:

首先遍历数据集的属性集,对于每一个属性j,我们优化上述目标。由于属性j有很多取值,那么从这些取值中先计算划分点,一般是相邻两个值的中间数作为划分点,这样我们的到划分点s的集合。举个例子,假如j有10个取值,那么先从小到大排序,然后可以计算10个取值中的划分点,相邻两个取值的平均值作为一个划分点,我们就可以得到9个划分点。

上述优化目标也就是,遍历每一个可能的j和s,寻找使得上述目标最小的j,s来划分当前结点。其中c1、c2是各分支的预测label(一般取分支结点的数据集的均值),R1、R2是各分支的样本子集。注意这里是用CART回归树举例,对于结点的划分只能产生两个分支。划分之后,递归地对子结点利用上述优化目标进行划分,直至到达递归边界(一般是限定叶子个数,最大深度等)。

得到这样的回归树之后,我们利用步骤(c)更新提升树的模型fm,并再次计算残差,又得到新的数据集(x,r),继续拟合生成新的回归树直至迭代到M。

下面我们进入正题,GBDT在BT上的改进之处是,初始化的f0(x)如下所示:

L是自己选的损失函数,若取MSE则c是label的均值。残差则变为:

m是指第m棵回归树,f是提升树模型,xi、yi则是数据集中的样本。这样,之前的简单作差就变为负梯度,我们将x与负梯度组合成新的数据集,用回归树去拟合,然后更新提升树的模型,这就是GBDT。


RF(Random Forest)

上文中GBDT是代表了Boosting这个集成方法,也就是利用负梯度一点点优化提升模型,只能串行计算。而此节要介绍的随机森林是代表了Bagging这个集成学习方法,可以并行计算。

首先直接摆上Bagging算法的伪码:

自主采样也就是bootstrap sampling,假定数据集含有m个样本,那么从该数据集中有放回地随机取m次,最终还是得到了含有m个样本的数据集,但是样本分布变了,也就是说有的样本可能重复了好几次,有的样本可能没有。

那么对于这样的数据集,我们总共生成T个,然后用基学习器去拟合数据集。当各个基学习器训练好后,对于新样本,我们用每个基学习器对其预测label,如果是分类就用服从多数的策略决定最终最终的预测label,如果是回归就用平均或加权平均(赋予基学习器权重)等策略。

RF则是以决策树为基学习器,以Bagging为基础,但是还增加了随机选取属性的特点。也就是,对于每个生成的随机样本集,我们还限制属性集,只取其中的一部分属性。假设总共有d个属性,推荐选取k=log(d)为属性子集的元素个数(log底数为2)。


DART(Dropouts meet Multiple Additive Regression Trees)

DART利用了深度神经网络中dropout设置的技巧,随机丢弃生成的决策树,然后再从剩下的决策树集中迭代优化提升树,这是DART的主要思想。下面直接上算法伪码来说DART与GBDT(MART)的不同之处和DART的原理:

刚开始时,还是初始化提升树模型为f0(x)=0,然后根据损失函数计算负梯度,并生成中间数据集,也就是S1,之后再利用回归树训练中间数据集得到T1,加入集合M中。

下面进入dropout环节,对M中的每棵树以Pdrop几率决定其是否被丢弃,若都不被丢弃,那么等概率随机选一棵。我们将丢弃的树加入集合D中,未被丢弃的树加入M帽中。

对于M帽中的树,我们按照传统GBDT的做法进行迭代更新,但是生成的新树需要被乘上一个正则化因子1/(|D|+1)。因为不丢弃树并产生新树时,我们迭代更新出来的提升树是被多迭代了|D|+1次负梯度,为了抵消这个差距,就需要正则化这一步。那么对于被丢弃的树,我们乘上|D|/(|D|+1)来统一数量级。

之后仍是随机丢弃树产生D,并在剩树的集合中进行GBDT中的做法。这样一看,当我们不丢弃任何树时,其实就是传统的GBDT,而丢弃所有树时就相当于RF,因为每次都得重新生成回归树,并没有之前的回归树作为基础。


lambdaMART

要介绍lambdaMART,我们就得先从RankNet说起。RankNet的实现既可以用神经网络来实现,也可以用决策树实现,总之它是将一个输入向量映射成一个实数。具体说来,给定一个数据集,而数据集是根据不同的query来划分的,对于每一个query,会有许多doc(查询的结果比如url等),这些doc自身的好坏我们不清楚,但是doc pair内与query谁更相关是已知的,这其实就是pair-wise。那么RankNet所做的就是将doc所转换成的feature映射成一个实数(其实就是对这个doc打分),也就是s = f(x),x就是doc feature,f是RankNet,s是分数。根据各个doc的分数,我们可以算出doc pair内一种偏序概率,如下所示:

(1)

Ui、Uj代表doc pair内的两个doc,这个Pij指的是Ui相比Uj对于query来说更相关的概率,Ui|>Uj指Ui比Uj更相关,Si、Sj指的是两个doc对应的分数,σ是该logistic函数的系数,自己指定一个就行。Pij只是通过分数S算出来的概率,是RankNet预测的结果,我们通过这个算出来的概率来计算损失,如下所示:

(2)

其中Pij帽指的是真实概率,假设Sij只能取0,1,-1三者之一,在doc i比doc j更相关时,Sij = 1,反之,Sij = -1,相等则为0,那么Pij帽 = (1/2)*(1+Sij),那么联合上述两式我们可以得到:

(3)

根据(1),我们可以得到Pij是(Si-Sj)的增函数(σ取正实数),也就是Si越比Sj大,就说明Pij越接近1。

所以当Sij = 1时,那么Pij越接近1则C越小,也就是说明预测得还行。

当Sij = -1时,那么Pji越接近1则C越小,也就是说明预测得还行。

而Si = Sj时,C = log2,当RankNet分辨不出来哪个更相关时,还是会有惩罚,也就是想要RankNet被训练得更鲁棒。

而我们用梯度下降法更新RankNet的权重时,下述导数得用到:

(4)

假设Wk为模型的参数,η为学习率,那么由随机梯度下降法得到:

(5)

若是用MART实现RankNet,则是直接计算(4)左式的相反数,然后与输入x生成中间数据集。

*************************************************************************************************************************************************

通过对梯度的因式分解,我们可以得到:

(6)

那么:

(7)

其中C = C(Si-Sj),这个不是C与(Si -Sj)相乘,而是表示函数句柄。

对于(5)中减数,我们通过(6)得到:

其中:

只是统一下符号,便于合并同类项。

其中I是doc pair{i,j}的集合,假设集合I中的doc pair是{Ui,Uj}并且Ui总是比Uj更相关,那么Sij总是等于1。我们在原来的λij后面乘上一个评价变化的因子,这样一变经实验验证效果更好,这个|△NDCG|是交换Ui,Uj的位置引起的NDCG指标的变化值,有如下式子:

这样我们改变了梯度的意义,之前我们优化目标是减小损失C,现在是增大NDCG的值,因为NDCG越大说明效果越好,我直接贴上NDCG的定义:

上述介绍其实就是lambdaRank,对RankNet做了两点改进,一是因式分解加速了训练,二就是|△NDCG|的引入。

*************************************************************************************************************************************************

lambdaMART与GBDT的不同之处在于将残差换为了λ,也就是说对每个样本(doc i),我们都求出它的λ,这个就是梯度,然后后面跟GBDT的算法基本一致,只不过加了二次优化。


XGBoost

首先回顾GBDT,它的大体流程如下:

其中求w也就是根据最小化损失函数求j、s,也就是最优属性及最优切分点,步长在上图中其实是shrinkage,原始GBDT直接是默认为1。GBDT是直接对损失函数L求负梯度作为预测值,就是上图中所示的2.1步,而XGBoost则对损失函数进行了二阶求导,如下图所示:

后面的Ω是正则化项,如下图所示:

然后我们直接让目标函数的导数为0,求得下图中的(5),(6)是代入w后的损失函数,w其实就是叶结点的预测值以及权重:

è¿éåå¾çæè¿°

我们还可以利用目标函数确定最优属性和最佳切分点,如下图所示:

然后其他的就与GBDT相同了,XGBoost实际上就是在GBDT基础上加了二次优化和正则项。


lightGBM

lightGBM主要是利用了大梯度单边采样、互斥特征绑定、直方图算法、leaf-wise策略等技巧使得训练速度大幅提升,内存消耗大量减少。下面分别介绍下这几个技巧。

大梯度单边采样:

对数据集中每个样本计算梯度,然后按降序排序,取前a*100%的样本作为大梯度子集,在剩下的样本(1-a)中随机取b*100%个样本作为小梯度子集,然后乘上(1-a)/b以保持数据分布不变,最后合并大梯度子集和小梯度子集作为新的训练集去训练决策树,在每次生成新树时都进行上述采样过程。

互斥特征绑定:

由于许多高维度的数据都是比较稀疏的,也就是含有许多0,那么进行特征绑定就可以减少特征的数量。举例说明,样本x含有10个特征,特征集是{a1,a2,...,a10},我们发现a1与a2取值互斥,也就是很少同时取非零值,假设a1取值范围为0~10,a2取值范围为0~20,而且它们不同时取非零值,那么对a2加一个偏置将其范围变为10~30,这样一来就可以将a1和a2两个特征捆绑起来,统一为一个特征a12,它的取值范围为0~30,x的特征数量就从10个变为9个了。

直方图算法:

将特征值离散化成k个整数,也就是k个bin的取值,然后将所有样本点它的该特征的取值情况选择bin,并统计bin中所含样本点个数。举例说明,有三个样本,分别为x1(0.1,1.1),x2(1.1,2.1),x3(0.2,3.1),首先将特征离散化,第一维的特征离散化成3个整数0、1、2,第二维的特征离散化成3个整数1、2、3,那么形成的直方图就是bin1[0] = 2,bin1[1] = 1,bin1[2] = 0,bin2[1] = 1,bin2[2] = 1,bin2[3] = 1。寻找最优属性和最佳切分点也是根据直方图来确定的,这样只需要扫描一次全部数据就能生成直方图,而GBDT和XGBoost每次寻找划分点时都要扫描全部的数据。

leaf-wise策略:

而XGBoost中则是这样的:

前者比后者会减少更多的loss,但是复杂度较高容易过拟合,但可以通过设置max-depth参数来克服。

lightGBM是可以基于GBDT的,也就是说计算叶子结点的预测值是可以通过GBDT的方式进行的,当然也可以用牛顿法(XGBoost)。


上述是我近期对决策树的一个总结,可能会有些错误,如有不清楚的地方,请及时与我沟通。

主要参考文献:

1.《机器学习》 周志华

2.《统计学习方法》李航

3.From RankNet to LambdaRank to LambdaMART: An Overview Christopher J.C. Burges

4.LightGBM: A Highly Efficient Gradient Boosting Decision Tree

5.DART: Dropouts meet Multiple Additive Regression Trees

  • 9
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值