树模型浅谈

 

1、树模型的进化

                                       |->bagging->RF

   ID3->C4.5->CART->|

                                       |->boosting->Adaboost->GBDT->xgboost                  

2、决策树

决策树是一个有监督的分类模型,本质是选择一个能带来最大信息增益的特征值进行分裂,直到到达结束条件或者叶子节点纯度到达一定阈值。决策树的每个非叶子节点表示一个特征属性上的测试,每个分支代表这个特征属性在某个值域上的输出。叶子节点存放一个类别,将存放的类别作为决策结果。

2.1、ID3:以信息增益为准则来选择最优划分属性

信息增益的计算基于信息熵,信息熵用来度量样本集合的纯度

             

eg:

假设于数据集D上建立决策树,数据有K个类别:

(1)中|Ck|/|D| 表示第k类样本的数据占数据集D样本总数的比例;
(2)H(D|A)表示的是以特征A作为分裂属性,得到的信息熵:Di表示的是以属性A为划分,分成n个分支,第i个分支的节点集合。因此,该公式求的是以属性A为划分,n个分支的信息熵总和
(3)为分割后与分割前的信息熵的差值,也就是信息增益,越大越好。

信息增益模型的缺点:

ID3决策树偏向于取值较多的属性进行分割,存在一定的偏好。为减小这一影响,有学者提出C4.5的分类算法。

 

2.2、C4.5:基于信息增益率准则选择最优分割属性的算法

信息增益比率通过引入一个被称作分裂信息(Split information)的项来惩罚取值较多的属性。

                                        

上式,分子计算与ID3一样,分母是由属性A的特征值个数决定的,个数越多,IV值越大,信息增益率越小,这样就可以避免模型偏好特征值多的属性。

C4.5缺点

  • 按照这个规则来分割,模型又会偏向特征数少的特征。

对于连续值属性来说,可取值数目不再有限,因此可以采用离散化技术(如二分法)进行处理。将属性值从小到大排序,然后选择中间值作为分割点,数值比它小的点被划分到左子树,数值不小于它的点被分到又子树,计算分割的信息增益率,选择信息增益率最大的属性值进行分割。

2.4、CART:以基尼系数为准则选择最优划分属性,可以应用于分类和回归

CART是一棵二叉树,采用二元切分法,每次把数据切成两份,分别进入左子树、右子树。而且每个非叶子节点都有两个孩子,所以CART的叶子节点比非叶子多1。相比ID3和C4.5,CART应用要多一些,既可以用于分类也可以用于回归。CART分类时,使用基尼指数(Gini)来选择最好的数据分割的特征,gini描述的是纯度,与信息熵的含义相似。CART中每一次迭代都会降低GINI系数。

Gini(D)反映了数据集D的纯度,值越小,纯度越高。我们在候选集合中选择使得划分后基尼指数最小的属性作为最优化分属性

3、分类树和回归树

提到决策树算法,很多想到的就是上面提到的ID3、C4.5、CART分类决策树。其实决策树分为分类树和回归树,前者用于分类,如晴天/阴天/雨天、用户性别、邮件是否是垃圾邮件,后者用于预测实数值,如明天的温度、用户的年龄等。

作为对比,先说分类树,我们知道ID3、C4.5分类树在每次分枝时,是穷举每一个特征属性的每一个阈值,找到使得按照feature<=阈值,和feature>阈值分成的两个分枝的信息增益最大的feature和阈值。按照该标准分枝得到两个新节点,用同样方法继续分枝直到所有人都被分入性别唯一的叶子节点,或达到预设的终止条件,若最终叶子节点中的性别不唯一,则以多数人的性别作为该叶子节点的性别。

回归树总体流程也是类似,不过在每个节点(不一定是叶子节点)都会得一个预测值,以年龄为例,该预测值等于属于这个节点的所有人年龄的平均值。分枝时穷举每一个feature的每个阈值找最好的分割点,但衡量最好的标准不再是最大熵,而是最小化均方差--每个人的预测误差平方和除以 N。这很好理解,被预测出错的人数越多,错的越离谱,均方差就越大,通过最小化均方差能够找到最靠谱的分枝依据。分枝直到每个叶子节点上人的年龄都唯一(这太难了)或者达到预设的终止条件(如叶子个数上限),若最终叶子节点上人的年龄不唯一,则以该节点上所有人的平均年龄做为该叶子节点的预测年龄

4、组合分类器

组合分类器是将多个分类器的结果进行多票表决或者取平均值,以此作为最终结果。Baggging 和Boosting都是模型融合的方法,可以将弱分类器融合之后形成一个强分类器,而且融合之后的效果会比最好的弱分类器更好。

Bagging的思想是每一次从原始数据中根据均匀概率分布有放回的抽取和原始数据大小相同的样本集合,样本点可能出现重复,然后对每一次产生的训练集构造一个分类器,再对分类器进行组合。

梯度提升的Boosting方式是使用代价函数对上一轮训练出的模型函数f的偏导来拟合残差。

4.1、构建组合分类器的好处:

  • 1)、提升模型精度:整合各个模型的分类结果,得到更合理的决策边界,减少整体错误,实现更好的分类效果;

  • 2)、处理过大或过小的数据集:数据集较大时,可以将数据集划分成多个子集,对子集构建分类器;数据集较小时,可通过多种抽样方式(bootstrap)从原始数据集抽样产生多组不同的数据集,构建分类器。

  • 3)、若决策边界过于复杂,则线性模型不能很好地描述真实情况。因此先对于特定区域的数据集,训练多个线性分类器,再将它们集成。

  • 4)、比较适合处理多源异构数据(存储方式不同(关系型、非关系型),类别不同(时序型、离散型、连续型、网络结构数据))

4.2、Bagging

          Bagging的思想比较简单,即每一次从原始数据中根据均匀概率分布有放回的抽取和原始数据大小相同的样本集合,样本点可能出现重复,然后对每一次产生的训练集构造一个分类器,再对分类器进行组合。

  • Bagging即套袋法,其算法过程如下:

  • 从原始样本集中抽取训练集。每轮从原始样本集中使用Bootstraping(有放回重复抽样)的方法抽取n个训练样本(在训练集中,有些样本可能被多次抽取到,而有些样本可能一次都没有被抽中)。共进行k轮抽取,得到k个训练集。(k个训练集之间是相互独立的)

  • 每次使用一个训练集得到一个模型,k个训练集共得到k个模型。(注:这里并没有具体的分类算法或回归方法,我们可以根据具体问题采用不同的分类或回归方法,如决策树、感知器等)

  • 对分类问题:将上步得到的k个模型采用投票的方式得到分类结果;对回归问题,计算上述模型的均值作为最后的结果。(所有模型的重要性相同)

4.3、Boosting

        AdaBoosting方式每次使用的是全部的样本,每轮训练改变样本的权重。下一轮训练的目标是找到一个函数f 来拟合上一轮的残差。当残差足够小或者达到设置的最大迭代次数则停止。Boosting会减小在上一轮训练正确的样本的权重,增大错误样本的权重。(对的残差小,错的残差大)。boosting的每一次抽样的样本分布都是不一样的。每一次迭代,都根据上一次迭代的结果,增加被错误分类的样本的权重,使得模型能在之后的迭代中更加注意到难以分类的样本,这是一个不断学习的过程,也是一个不断提升的过程,这也就是boosting思想的本质所在。迭代之后,将每次迭代的基分类器进行集成。那么如何进行样本权重的调整和分类器的集成是我们需要考虑的关键问题。

        梯度提升的Boosting方式是使用代价函数对上一轮训练出的模型函数f的偏导来拟合残差。

                            

4.4、Bagging,Boosting二者之间的区别

1)样本选择上:

  • Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。
  • Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化。而权值是根据上一轮的分类结果进行调整。

2)样例权重:

  • Bagging:使用均匀取样,每个样例的权重相等
  • Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。

3)预测函数:

  • Bagging:所有预测函数的权重相等。
  • Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重。

4)并行计算:

  • Bagging:各个预测函数可以并行生成
  • Boosting:各个预测函数只能顺序生成,因为后一个模型参数需要前一轮模型的结果。

5)优化目标

  • bagging是减少variance,而boosting是减少bias

通常来说boosting是在优化loss function,在降低loss,那么很显然,这在很大程度上是减少bias。
而bagging,之所以进行bagging,是希望模型能够具有更好的鲁棒性,也就是稳定性,希望避免过拟合,显然这就是在减少variance。

 期望服从线性运算:

                                

方差不服从线性运算:

                  

期望,方差之间的运算详细参考:https://blog.csdn.net/MissXy_/article/details/80705828

 

5、随机森林(RF)

随机森林是一个多棵决策树的组合分类器。主要包括两方面:数据的随机选取,以及待选特征的随机选取

1.数据的随机选取
第一,从原始的数据集中采取有放回的抽样(bootstrap),构造子数据集,子数据集的数据量是和原始数据集相同的。不同子数据集的元素可以重复,同一个子数据集中的元素也可以重复。
第二,利用子数据集来构建子决策树,将这个数据放到每个子决策树中,每个子决策树输出一个结果。最后,如果有了新的数据需要通过随机森林得到分类结果,就可以通过对子决策树的判断结果的投票,得到随机森林的输出结果了。如下图,假设随机森林中有3棵子决策树,2棵子树的分类结果是A类,1棵子树的分类结果是B类,那么随机森林的分类结果就是A类。

2、待选特征的随机选取:
与数据集的随机选取类似,随机森林中的子树的每一个分裂过程并未用到所有的待选特征,而是从所有的待选特征中随机选取一定的特征,之后再在随机选取的特征中选取最优的特征。这样能够使得随机森林中的决策树都能够彼此不同,提升系统的多样性,从而提升分类性能。

6、Adaboost

        Adaboost每一次抽样的样本分布都是不一样的。每一次迭代,都根据上一次迭代的结果,增加被错误分类的样本的权重,使得模型能在之后的迭代中更加注意到难以分类的样本,这是一个不断学习的过程,也是一个不断提升的过程

eg:我们有一个数据集,样本大小为N,每一个样本对应一个原始标签起初,

  • 我们初始化样本的权重为1/N

             

  • em计算的是当前数据下,模型的分类误差率,模型的系数值是基于分类误差率的  

            preview

  • 根据模型的分类结果,更新原始数据中数据的分布,增加被错分的数据被抽中的概率,以便下一次迭代的时候能被模型重新训练

                   

  • 最终的分类器是各个基分类器的组合

                  preview                       

7、GBDT

7.1、GBDT结构

GBDT是以决策树(CART)为基学习器的GB算法,是迭代树,而不是分类树。Boost是"提升"的意思,一般Boosting算法都是一个迭代的过程,每一次新的训练都是为了改进上一次的结果。

                     

GBDT的核心就在于:每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量。比如A的真实年龄是18岁,但第一棵树的预测年龄是12岁,差了6岁,即残差为6岁。那么在第二棵树里我们把A的年龄设为6岁去学习,如果第二棵树真的能把A分到6岁的叶子节点,那累加两棵树的结论就是A的真实年龄;如果第二棵树的结论是5岁,则A仍然存在1岁的残差,第三棵树里A的年龄就变成1岁,继续学习。

7.2、GBDT实例

训练一个提升树模型来预测年龄:
  训练集是4个人,A,B,C,D年龄分别是14,16,24,26。样本中有购物金额、上网时长、经常到百度知道提问等特征。提升树的过程如下:

7.3、GBDT算法学习过程

GBDT 算法可以看成是由 K 棵树组成的加法模型:

                  

学习加法模型,可以用前向分布算法(forward stagewise algorithm)。因为学习的是加法模型,如果能够从前往后,每一步只学习一个基函数及其系数(结构),逐步逼近优化目标函数,那么就可以简化复杂度。这一学习过程称之为 Boosting。具体地,我们从一个常量预测开始,每次学习一个新的函数,过程如下:                     

                

目标函数通常定义为如下形式:

其中,L 是损失函数,用来衡量模型拟合训练数据的好坏程度;Ω称之为正则项,用来衡量学习到的模型的复杂度。

对正则项的优化鼓励算法学习到较简单的模型,简单模型一般在测试样本上的预测结果比较稳定、方差较小(奥坎姆剃刀原则)。也就是说,优化损失函数尽量使模型走出欠拟合的状态,优化正则项尽量使模型避免过拟合。

在第 t 步,这个时候目标函数可以写为:

损失函数有方差损失,逻辑损失,0-1损失,对数损失等:当损失函数为方差损失时,每一步拟合为拟合前一颗树的残差

举例说明,假设损失函数为平方损失(square loss),则目标函数为:

其中,称之为残差(residual)。因此,使用平方损失函数时,GBDT 算法的每一步在生成决策树时只需要拟合前面的模型的残差。

7.4、GBDT优缺点

  • GBDT 它的非线性变换比较多,表达能力强,而且不需要做复杂的特征工程和特征变换。
  • GBDT 的缺点也很明显,Boost 是一个串行过程,不好并行化,而且计算复杂度高,同时不太适合高维稀疏特征;
  • 传统 GBDT 在优化时只用到一阶导数信息。

8、XGBoost

Xgboost相比于GBDT来说,更加有效应用了数值优化,最重要是对损失函数(预测值和真实值的误差)变得更复杂。目标函数依然是所有树的预测值相加等于预测值。

损失函数如下,引入了一阶导数,二阶导数。:

8.1、泰勒公式 

(我在面试的过程中被要求推导过)

泰勒公式简单的理解,就是函数某个点的取值可以用参考点取值和 n+1 阶导数的来表示,而且这个公式是有规律的比较好记。

根据泰勒公式把函数在x点处二阶展开,可得到如下等式:

看成,则等式(1) 可转化为:

假设损失函数为平方损失函数,把对应的一阶导数和二阶导数代入等式(4) 即得等式(2)。

由于函数中的常量在函数最小化的过程中不起作用,因此我们可以从等式(4) 中移除掉常量项,得:

8.2、 决策过程

preview

树的复杂度可以用树的分支数目来衡量,树的分支我们可以用叶子结点的数量来表示

那么树的复杂度式子:右边第一项是叶子结点的数量T,第二项是树的叶子结点权重w的l2正则化,正则化是为了防止叶子结点过多;

此时,每一次迭代,相当于在原有模型中增加一棵树,目标函数中,我们用wq(x)表示一棵树,包括了树的结构以及叶子结点的权重,w表示权重(反映预测的概率),q表示样本所在的索引号(反映树的结构)

定义集合    为所有被划分到叶子节点的训练样本的集合。等式(5) 可以根据树的叶子节点重新组织为 T 个独立的二次函数的和:

 

定义

因为一元二次函数最小值处,一阶导数等于 0:

此时,目标函数的值为

综上,为了便于理解,单颗决策树的学习过程可以大致描述为: 1. 枚举所有可能的树结构 q 2. 用等式(8) 为每个 q 计算其对应的分数 Obj,分数越小说明对应的树结构越好 3. 根据上一步的结果,找到最佳的树结构,用等式(7) 为树的每个叶子节点计算预测值

然而,可能的树结构数量是无穷的,所以实际上我们不可能枚举所有可能的树结构。通常情况下,我们采用贪心策略来生成决策树的每个节点。

1. 从深度为 0 的树开始,对每个叶节点枚举所有的可用特征 2. 针对每个特征,把属于该节点的训练样本根据该特征值升序排列,通过线性扫描的方式来决定该特征的最佳分裂点,并记录该特征的最大收益(采用最佳分裂点时的收益) 3. 选择收益最大的特征作为分裂特征,用该特征的最佳分裂点作为分裂位置,把该节点生长出左右两个新的叶节点,并为每个新节点关联对应的样本集 4. 回到第 1 步,递归执行到满足特定条件为止

8.3、 选择最优分割点

如何计算每次分裂的收益呢?假设当前节点记为 C,分裂之后左孩子节点记为 L,右孩子节点记为 R,则该分裂获得的收益定义为当前节点的目标函数值减去左右两个孩子节点的目标函数值之和:

根据等式(8) 可得:

其中,项表示因为增加了树的复杂性(该分裂增加了一个叶子节点)带来的惩罚。

xgboost的迭代是以下图中gain式子定义的指标选择最优分割点的:

preview

一种办法是贪心算法,遍历一个节点内的所有特征,按照公式计算出按照每一个特征分割的信息增益,找到信息增益最大的点进行树的分割。增加的新叶子惩罚项对应了树的剪枝,当gain小于某个阈值的时候,我们可以剪掉这个分割。但是这种办法不适用于数据量大的时候,因此,我们需要运用近似算法。

另一种方法:XGBoost在寻找splitpoint的时候,不会枚举所有的特征值,而会对特征值进行聚合统计,按照特征值的密度分布,构造直方图计算特征值分布的面积,然后划分分布形成若干个bucket(桶),每个bucket的面积相同,将bucket边界上的特征值作为splitpoint的候选,遍历所有的候选分裂点来找到最佳分裂点。

上图近似算法公式的解释:将特征k的特征值进行排序,计算特征值分布,rk(z)表示的是对于特征k而言,其特征值小于z的权重之和占总权重的比例,代表了这些特征值的重要程度,我们按照这个比例计算公式,将特征值分成若干个bucket,每个bucket的比例相同,选取这几类特征值的边界作为划分候选点,构成候选集;选择候选集的条件是要使得相邻的两个候选分裂节点差值小于某个阈值

最后,总结一下 xgboost的学习算法:

  • 1. 算法每次迭代生成一颗新的决策树 ;
  • 2. 在每次迭代开始之前,计算损失函数在每个训练样本点的一阶导数和二阶导数 ;
  • 3. 通过贪心策略生成新的决策树,通过等式(7) 计算每个叶节点对应的预测值
  • 4. 把新生成的决策树ft(xi)添加到模型中
  •  

8.4、 xgboost与gbdt比较

综合以上的解说,我们可以得到xgboost相比于GBDT的创新之处:

传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。

  • 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。
  • xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。
  • Shrinkage(缩减),相当于学习速率(xgboost中的eta)。每次迭代,增加新的模型,在前面成上一个小于1的系数,降低优化的速度,每次走一小步逐步逼近最优模型比每次走一大步逼近更加容易避免过拟合现象;
  • 列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样(即每次的输入特征不是全部特征),不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。
  • 忽略缺失值:在寻找splitpoint的时候,不会对该特征为missing的样本进行遍历统计,只对该列特征值为non-missing的样本上对应的特征值进行遍历,通过这个工程技巧来减少了为稀疏离散特征寻找splitpoint的时间开销
  • 指定缺失值的分隔方向:可以为缺失值或者指定的值指定分支的默认方向,为了保证完备性,会分别处理将missing该特征值的样本分配到左叶子结点和右叶子结点的两种情形,分到那个子节点带来的增益大,默认的方向就是哪个子节点,这能大大提升算法的效率。
  • 并行化处理:在训练之前,预先对每个特征内部进行了排序找出候选切割点,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行,即在不同的特征属性上采用多线程并行方式寻找最佳分割点。

 

参考网址:

https://www.jianshu.com/p/52a2693db3c8  (树模型总结)

https://zhuanlan.zhihu.com/p/34534004  (树模型总结)

https://www.cnblogs.com/earendil/p/8872001.html (bagging和boosting总结)

https://blog.csdn.net/MissXy_/article/details/80705828  (期望和方差的计算)

https://www.jianshu.com/p/005a4e6ac775 (GBDT详解)

https://cloud.tencent.com/developer/article/1005611 (GBDT详解,个人觉得这篇文章把xgboost的原理说成了GDBT的,但是挺详细的)

 

  • 3
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值