【机器学习】GBDT梯度提升树

推荐收藏 | 又有10道XGBoost面试题送给你-腾讯云开发者社区-腾讯云

1. XGBoost如何处理不平衡数据

对于不平衡的数据集,例如用户的购买行为,肯定是极其不平衡的,这对XGBoost的训练有很大的影响,XGBoost有两种自带的方法来解决:

第一种,如果你在意AUC,采用AUC来评估模型的性能,那你可以通过设置scale_pos_weight来平衡正样本和负样本的权重。例如,当正负样本比例为1:10时,scale_pos_weight可以取10;

第二种,如果你在意概率(预测得分的合理性),你不能重新平衡数据集(会破坏数据的真实分布),应该设置max_delta_step为一个有限数字来帮助收敛(基模型为LR时有效)。

原话是这么说的:

For common cases such as ads clickthrough log, the dataset is extremely imbalanced. This can affect the training of xgboost model, 
and there are two ways to improve it.
  If you care only about the ranking order (AUC) of your prediction
      Balance the positive and negative weights, via scale_pos_weight
      Use AUC for evaluation
  If you care about predicting the right probability
      In such a case, you cannot re-balance the dataset
      In such a case, set parameter max_delta_step to a finite number (say 1) will help convergence

那么,源码到底是怎么利用scale_pos_weight来平衡样本的呢,是调节权重还是过采样呢?请看源码:

if (info.labels[i] == 1.0f)  w *= param_.scale_pos_weight

可以看出,应该是增大了少数样本的权重。

除此之外,还可以通过上采样、下采样、SMOTE算法或者自定义代价函数的方式解决正负样本不平衡的问题。


XGBoost和LightGBM的区别

(1)树生长策略:XGB采用level-wise的分裂策略,LGB采用leaf-wise的分裂策略。XGB对每一层所有节点做无差别分裂,但是可能有些节点增益非常小,对结果影响不大,带来不必要的开销。Leaf-wise是在所有叶子节点中选取分裂收益最大的节点进行的,但是很容易出现过拟合问题,所以需要对最大深度做限制 。

(2)分割点查找算法:XGB使用特征预排序算法,LGB使用基于直方图的切分点算法,其优势如下:

  • 减少内存占用,比如离散为256个bin时,只需要用8位整形就可以保存一个样本被映射为哪个bin(这个bin可以说就是转换后的特征),对比预排序的exact greedy算法来说(用int_32来存储索引+ 用float_32保存特征值),可以节省7/8的空间。
  • 计算效率提高,预排序的Exact greedy对每个特征都需要遍历一遍数据,并计算增益,复杂度为?(#???????×#????)。而直方图算法在建立完直方图后,只需要对每个特征遍历直方图即可,复杂度为?(#???????×#????)。
  • LGB还可以使用直方图做差加速,一个节点的直方图可以通过父节点的直方图减去兄弟节点的直方图得到,从而加速计算

但实际上xgboost的近似直方图算法也类似于lightgbm这里的直方图算法,为什么xgboost的近似算法比lightgbm还是慢很多呢? xgboost在每一层都动态构建直方图, 因为xgboost的直方图算法不是针对某个特定的feature,而是所有feature共享一个直方图(每个样本的权重是二阶导),所以每一层都要重新构建直方图,而lightgbm中对每个特征都有一个直方图,所以构建一次直方图就够了。

(3)支持离散变量:无法直接输入类别型变量,因此需要事先对类别型变量进行编码(例如独热编码),而LightGBM可以直接处理类别型变量。

(4)缓存命中率:XGB使用Block结构的一个缺点是取梯度的时候,是通过索引来获取的,而这些梯度的获取顺序是按照特征的大小顺序的,这将导致非连续的内存访问,可能使得CPU cache缓存命中率低,从而影响算法效率。而LGB是基于直方图分裂特征的,梯度信息都存储在一个个bin中,所以访问梯度是连续的,缓存命中率高。

(5)LightGBM 与 XGboost 的并行策略不同:

  • 特征并行 :LGB特征并行的前提是每个worker留有一份完整的数据集,但是每个worker仅在特征子集上进行最佳切分点的寻找;worker之间需要相互通信,通过比对损失来确定最佳切分点;然后将这个最佳切分点的位置进行全局广播,每个worker进行切分即可。XGB的特征并行与LGB的最大不同在于XGB每个worker节点中仅有部分的列数据,也就是垂直切分,每个worker寻找局部最佳切分点,worker之间相互通信,然后在具有最佳切分点的worker上进行节点分裂,再由这个节点广播一下被切分到左右节点的样本索引号,其他worker才能开始分裂。二者的区别就导致了LGB中worker间通信成本明显降低,只需通信一个特征分裂点即可,而XGB中要广播样本索引。
  • 数据并行 :当数据量很大,特征相对较少时,可采用数据并行策略。LGB中先对数据水平切分,每个worker上的数据先建立起局部的直方图,然后合并成全局的直方图,采用直方图相减的方式,先计算样本量少的节点的样本索引,然后直接相减得到另一子节点的样本索引,这个直方图算法使得worker间的通信成本降低一倍,因为只用通信以此样本量少的节点。XGB中的数据并行也是水平切分,然后单个worker建立局部直方图,再合并为全局,不同在于根据全局直方图进行各个worker上的节点分裂时会单独计算子节点的样本索引,因此效率贼慢,每个worker间的通信量也就变得很大。
  • 投票并行(LGB):当数据量和维度都很大时,选用投票并行,该方法是数据并行的一个改进。数据并行中的合并直方图的代价相对较大,尤其是当特征维度很大时。大致思想是:每个worker首先会找到本地的一些优秀的特征,然后进行全局投票,根据投票结果,选择top的特征进行直方图的合并,再寻求全局的最优分割点。

梯度提升树(Gradient Boosting Decison Tree, 以下简称GBDT)属于Boosting家族。

在解决回归问题时,如果损失函数是均方误差损失函数则求解残差为(真实值-预测值)。但是当损失函数是其他的时候,我们用损失函数的负梯度在当前模型的值,将它作为残差的估计。对于平方损失函数,它就是所说的残差;对于一般损失函数,它是残差的近似

对于二分类问题,提升树(注意是提升树)算法只需将adaboost算法中的基分类器限制为二类分类树即可。在损失函数是指数损失函数的时候,残差是(真实值-预测值)。不是指数损失的话,就变成GBDT,用损失函数的负梯度在当前模型的值作为残差的近似值,这是利用最速下降法的近似方法。

gbdt二分类算法流程

提升树利用加法模型与前向分步算法实现学习的优化过程,当损失函数是平方损失和指数损失函数时,每一步的优化是很简单的,但对一般损失函数而言,往往每一步优化并不是十分容易,针对这一问题,Freidman提出了梯度提升算法,这是利用最速下降法的近似方法,其关键是利用损失函数的负梯度在当前模型的值作为提升树算法中的残差的近似值,拟合一个回归树,即:

则GBDT算法的一般流程是:


  • gbdt 的算法的流程?

  • gbdt 如何选择特征 ?

CART 生成的过程其实就是一个选择特征的过程。假设目前总共有 M 个特征。第一步需要从中选择出一个特征 j,做为二叉树的第一个节点。然后对特征 j 的值选择一个切分点 m。 一个样本的特征 j 的值如果小于m,则分为一类,如果大于m,则分为另外一类。如此便构建了CART 树的一个节点。其他节点的生成过程和这个是一样的。现在的问题是在每轮迭代的时候,如何选择这个特征 j,以及如何选择特征 j 的切分点 m:

  • 原始的gbdt的做法非常的暴力,首先遍历每个特征,然后对每个特征遍历它所有可能的切分点,找到最优特征 m 的最优切分点 j。
  • 如何衡量我们找到的特征 m和切分点 j 是最优的呢?先遍历训练样本的所有的特征,对于特征 j,我们遍历特征 j 所有特征值的切分点 c。找到可以让下面这个式子最小的特征 j 以及切分点c。

  • gbdt 如何用于分类?

         首先明确一点,gbdt 无论用于分类还是回归一直都是使用的CART 回归树。不会因为任务是分类任务就选用分类树,这里面的核心是因为gbdt 每轮的训练是在上一轮的训练的残差基础之上进行训练的。这里的残差就是当前模型的负梯度值 。这个要求每轮迭代的时候,弱分类器的输出的结果相减是有意义的。残差相减是有意义的。

        如果选用的弱分类器是分类树,类别相减是没有意义的。上一轮输出的是样本 x 属于 A类,本一轮训练输出的是样本 x 属于 B类。 A 和 B 很多时候甚至都没有比较的意义,A 类减B类是没有意义的。

        我们具体到分类这个任务上面来,我们假设样本 X 总共有K类。来了一个样本 x,我们需要使用gbdt来判断 x 属于样本的哪一类。

                                  图 gbdt 多分类算法流程

         第一步,在训练的时候,是针对样本 X 每个可能的类都训练一个分类回归树。举例说明,目前样本有三类,也就是 K = 3。样本 x 属于第二类。那么针对该样本 x 的分类结果,其实我们可以用一个 三维向量 [0,1,0] 来表示。0表示样本不属于该类,1表示样本属于该类。由于样本已经属于第二类了,所以第二类对应的向量维度为1,其他位置为0。

        针对样本有三类的情况,我们实质上是在每轮的训练的时候是同时训练三颗树。第一颗树针对样本x的第一类,输入为(x,0)。第二颗树输入针对样本 x 的第二类,输入为(x,1)。第三颗树针对样本 x 的第三类,输入为(x,0)。

        在这里每颗树的训练过程其实就是CATR TREE 的生成过程。在此处我们参照之前的生成树的程序即可解出三颗树,以及三颗树对 x 类别的预测值f1(x),f2(x),f3(x)。那么在此类训练中,我们仿照多分类的逻辑回归 ,使用softmax 来产生概率,则属于类别 1 的概率

并且我们我们可以针对类别 1 求出残差;类别 2 求出残差;类别 3 求出残差

        然后开始第二轮训练,针对第一类 输入为, 针对第二类输入为,针对第三类输入为,继续训练出三颗树。一直迭代M轮。每轮构建 3颗树。

        所以当K =3。我们其实应该有三个式子

当训练完毕以后,新来一个样本 x1 ,我们需要预测该样本的类别的时候,便可以有这三个式子产生三个值,f1(x),f2(x),f3(x)。样本属于某个类别c的概率为

  • gbdt 通过什么方式减少误差 ?

和boosting系列一样,每次迭代都减小误差。

  • gbdt的效果相比于传统的LR,SVM效果为什么好一些 ?

 1) 可以灵活处理各种类型的数据,包括连续值和离散值。而LR只能处理离散值。

 2) 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。

  • gbdt 如何加速训练?

由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。

  • gbdt的参数有哪些,如何调参 ?

首先,我们来看boosting框架相关的重要参数。由于GradientBoostingClassifier和GradientBoostingRegressor的参数绝大部分相同,我们下面会一起来讲,不同点会单独指出。

  1) n_estimators: 也就是弱学习器的最大迭代次数,或者说最大的弱学习器的个数。一般来说n_estimators太小,容易欠拟合,n_estimators太大,又容易过拟合,一般选择一个适中的数值。默认是100。在实际调参的过程中,我们常常将n_estimators和下面介绍的参数learning_rate一起考虑。

  2) learning_rate: 即每个弱学习器的权重缩减系数νν,也称作步长,在原理篇的正则化章节我们也讲到了,加上了正则化项,我们的强学习器的迭代公式为。ν的取值范围为0<ν≤1。对于同样的训练集拟合效果,较小的ν意味着我们需要更多的弱学习器的迭代次数。通常我们用步长和迭代最大次数一起来决定算法的拟合效果。所以这两个参数n_estimators和learning_rate要一起调参。一般来说,可以从一个小一点的ν开始调参,默认是1。

    3) subsample: 即我们在原理篇的正则化章节讲到的子采样,取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间,默认是1.0,即不使用子采样。

   4) init: 即我们的初始化的时候的弱学习器,拟合对应原理篇里面的f0(x),如果不输入,则用训练集样本来做样本集的初始化分类回归预测。否则用init参数提供的学习器做初始化分类回归预测。一般用在我们对数据有先验知识,或者之前做过一些拟合的时候,如果没有的话就不用管这个参数了。

   5) loss: 即我们GBDT算法中的损失函数。分类模型和回归模型的损失函数是不一样的。

 对于分类模型,有对数似然损失函数"deviance"和指数损失函数"exponential"两者输入选择。默认是对数似然损失函数"deviance"。在原理篇中对这些分类损失函数有详细的介绍。一般来说,推荐使用默认的"deviance"。它对二元分离和多元分类各自都有比较好的优化。而指数损失函数等于把我们带到了Adaboost算法。

 对于回归模型,有均方差"ls", 绝对损失"lad", Huber损失"huber"和分位数损失“quantile”。默认是均方差"ls"。一般来说,如果数据的噪音点不多,用默认的均方差"ls"比较好。如果是噪音点较多,则推荐用抗噪音的损失函数"huber"。而如果我们需要对训练集进行分段预测的时候,则采用“quantile”。

     6) alpha:这个参数只有GradientBoostingRegressor有,当我们使用Huber损失"huber"和分位数损失“quantile”时,需要指定分位数的值。默认是0.9,如果噪音点较多,可以适当降低这个分位数的值。

  • GBDT和随机森林的相同点:

  1. 都是由多棵树组成
  2. 最终的结果都是由多棵树一起决定
  • GBDT和随机森林的不同点:

  1. 组成随机森林的树可以是分类树,也可以是回归树;而GBDT只由回归树组成
  2. 组成随机森林的树可以并行生成;而GBDT只能是串行生成
  3. 对于最终的输出结果而言,随机森林采用多数投票等;而GBDT则是将所有结果累加起来,或者加权累加起来
  4. 随机森林对异常值不敏感,GBDT对异常值非常敏感
  5. 随机森林对训练集一视同仁,GBDT是基于权值的弱分类器的集成
  6. 随机森林是通过减少模型方差提高性能,GBDT是通过减少模型偏差提高性能
  • gbdt的优缺点 ?

GBDT主要的优点有:

  1. 可以灵活处理各种类型的数据,包括连续值和离散值。
  2. 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
  3. 使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数

GBDT的主要缺点有:

  1. 由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。
  • GBDT如何正则化

  • gbdt 如何构建特征 ?

         其实说gbdt 能够构建特征并非很准确,gbdt 本身是不能产生特征的,但是我们可以利用gbdt去产生特征的组合。在CTR预估中,工业界一般会采用逻辑回归去进行处理,在我的上一篇博文当中已经说过,逻辑回归本身是适合处理线性可分的数据,如果我们想让逻辑回归处理非线性的数据,其中一种方式便是组合不同特征,增强逻辑回归对非线性分布的拟合能力。

        长久以来,我们都是通过人工的先验知识或者实验来获得有效的组合特征,但是很多时候,使用人工经验知识来组合特征过于耗费人力,造成了机器学习当中一个很奇特的现象:有多少人工就有多少智能。关键是这样通过人工去组合特征并不一定能够提升模型的效果。所以我们的从业者或者学界一直都有一个趋势便是通过算法自动,高效的寻找到有效的特征组合。Facebook 在2014年 发表的一篇论文便是这种尝试下的产物,利用gbdt去产生有效的特征组合,以便用于逻辑回归的训练,提升模型最终的效果。

               图 :用GBDT 构造特征

 如图所示,我们 使用 GBDT 生成了两棵树,两颗树一共有五个叶子节点。我们将样本 X 输入到两颗树当中去,样本X 落在了第一棵树的第二个叶子节点,第二颗树的第一个叶子节点,于是我们便可以依次构建一个五纬的特征向量,每一个纬度代表了一个叶子节点,样本落在这个叶子节点上面的话那么值为1,没有落在该叶子节点的话,那么值为 0.

        于是对于该样本,我们可以得到一个向量[0,1,0,1,0] 作为该样本的组合特征,和原来的特征一起输入到逻辑回归当中进行训练。实验证明这样会得到比较显著的效果提升。

  • GBDT的“梯度提升”体现在那个阶段

在构建cart树时使用了损失函数的负梯度,而不是所谓的残差=真值-预测值实际上是一种更宽广的概念,但是在平方损失的情况下,上面等式是成立的。另外使用损失函数的梯度可以保证损失函数最小值。所以GBDT的梯度提升体现在构建cart树的所需的负梯度阶段,其利用最速下降的近似方法。

  • GBDT如何做特征选择

  • GBDT那些部分可以并行(即加速训练)

  1. 计算每个样本的负梯度; 
  2. 分裂挑选最佳特征及其分割点时,对特征计算相应的误差及均值时; 
  3. 更新每个样本的负梯度时; 
  4. 最后预测过程中,每个样本将之前的所有树的结果累加的时候。
  • GBDT与RF的区别

相同点: 

  1. GBDT与RF都是采用多棵树组合作为最终结果;这是两者共同点。 

不同点: 

  1. RF的树可以是回归树也可以是分类树,而GBDT只能是回归树。 
  2. RF中树是独立的,相互之间不影响,可以并行;而GBDT树之间有依赖,是串行。 
  3. RF最终的结果是有多棵树表决决定,而GBDT是有多棵树叠加组合最终的结果。 
  4. RF对异常值不敏感,原因是多棵树表决,而GBDT对异常值比较敏感,原因是当前的错误会延续给下一棵树。 
  5. RF是通过减少模型的方差来提高性能,而GBDT是减少模型的偏差来提高性能的。(原理之前分析过) 
  6. RF不需要进行数据预处理,即特征归一化。而GBDT则需要进行特征归一化
  • GBDT如何解决分类?

(因为不管是处理回归还是处理分类,都是用的CART回归树,参考4里很详细!)

一些题目?


For example, you should be able to describe the differences and commonalities between gradient boosted trees and random forests. 

So random forests and boosted trees are really the same models; the difference arises from how we train them.

参考:

1、梯度提升树(GBDT)原理小结

2、机器学习算法中 GBDT 和 XGBOOST 的区别有哪些? - wepon的回答 

3、GBDT+LR算法解析及Python实现

4、机器学习算法GBDT的面试要点总结-上篇(写的都超棒!)

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值