目录
一、GBDT概述
二、GBDT算法思想
1. GB(Gradient boosting)
2. GBDT的变形和参数建议
3. 算法思想总结
4. GBDT的优缺点
三、GBDT回归算法
1. 回归算法
2. 回归实例
四、GBDT分类算法
1. 二元分类
2. 多元分类
3. 分类实例
五、常见问题
1. 随机森林和 GBDT 的区别
2. Xgboost和GBDT的区别
2. xgboost,rf,lr优缺点及场景
3. xgboost和lightgbm的区别和适用场景
4. N问GBDT
Gradient boosting的思想是迭代生多个(M个)弱的模型,然后将每个弱模型的预测结果相加,即加法模型:
在GBDT的迭代中,假设我们前一轮迭代得到的强学习器是, 损失函数是, 我们本轮迭代的目标是找到一个CART回归树模型的弱学习器,让本轮的损失函数最小。也就是说,本轮迭代找到决策树,优化或者说最小化loss Function.
由此可看出,目标有两个:
GB算法的思想很简单,关键是怎么生成h(x)?
如果目标函数是回归问题的均方误差,很容易想到最理想的h(x)应该是能够完全拟合 ,这就是常说基于残差的学习。残差学习在回归问题中可以很好的使用,但是为了一般性(分类,排序问题),实际中往往是基于loss Function 在函数空间的的负梯度学习,对于回归问题残差和负梯度也是相同的。中的f,不要理解为传统意义上的函数,而是一个函数向量,向量中元素的个数与训练样本的个数相同,因此基于Loss Function函数空间的负梯度的学习也称为“伪残差”。GBDT的核心就在于,每一棵树学的是之前所有树结论和的残差,这个残差就是一个加预测值后能得真实值的累加量
让损失函数沿着梯度方向的下降。这个就是gbdt 的 gb的核心了。 利用损失函数的负梯度在当前模型的值作为回归问题提升树算法中的残差的近似值去拟合一个回归树。gbdt 每轮迭代的时候,都去拟合损失函数在当前模型下的负梯度
GB算法的步骤:
1.初始化模型为常数值:
2.迭代生成M个基学习器
(1).计算伪残差
(2).基于生成基学习器
(3).计算最优的
(4).更新模型
传统回归树与GBDT的区别:
年龄预测为例,简单起见训练集只有4个人,A,B,C,D,年龄分别是14,16,24,26。其中A,B分别是高一和高三学生;C,D分别是应届毕业生和工作两年的员工。
如果用一棵传统的回归决策树来训练,会得到如下图1所示结果:
使用GBDT,由于数据太少,我们限定叶子节点最多有两个,即每棵树都只有一个分枝,并且限定只学两棵树。我们会得到如下图2所示结果:
既然图1和图2 最终效果相同,为何还需要GBDT呢?答案是过拟合。我们发现图1为了达到100%精度使用了3个feature(上网时长、时段、网购金额)相对来说图2的boosting虽然用了两棵树 ,但其实只用了2个feature就搞定
GBDT的一个重要的参数就是每个决策树的深度。如果每次迭代时树都完全长成,那么其实就成为了一个基本的决策树,会导致过拟合,也失去了Boost算法的意义。通常设置决策树的深度为6,。但同时也要看应用场景。
GBDT在实际运用时,常常有两种变体:
“Shrinkage”:事实上这是一种正则化(regularization)方法,为了进一步过拟合,在每次对残差估计进行迭代时,不直接加上当前步所拟合的残差,而是乘以一个系数。
其中,为当前回归树残差,λ为1时,即为不加Shrinkage的一般GBDT。有文章指出,10 < λ * 迭代次数(或者说数的数目)< 100,是一个比较合适的学习速率。但是一般这个速率常常被设成了0.1,或者0.05。
“Subsample”:第二种正则化的方式是通过子采样比例(subsample)。取值为(0,1]。注意这里的子采样和随机森林不一样,随机森林使用的是放回抽样,而这里是不放回抽样。如果取值为1,则全部样本都使用,等于没有使用子采样。如果取值小于1,则只有一部分样本会去做GBDT的决策树拟合。选择小于1的比例可以减少方差,即防止过拟合,但是会增加样本拟合的偏差,因此取值不能太低。推荐在[0.5, 0.8]之间。使用了子采样的GBDT有时也称作随机梯度提升树(Stochastic Gradient Boosting Tree, SGBT)。由于使用了子采样,程序可以通过采样分发到不同的任务去做boosting的迭代过程,最后形成新树,从而减少弱学习器难以并行学习的弱点。
GBDT可以看做:
线性加法模型+前向分步算法+损失函数
(1)加法模型与前向分步算法
(2)损失函数
GBDT有绝对值损失、Huber损失和平方损失的等,Huber损失如下:
除此之外,常见的损失函数如下:
GBDT主要的优点有:
1) 可以灵活处理各种类型的数据,包括连续值和离散值。
2) 在相对少的调参时间情况下,预测的准确率也可以比较高。这个是相对SVM来说的。
3)使用一些健壮的损失函数,对异常值的鲁棒性非常强。比如 Huber损失函数和Quantile损失函数。
GBDT的主要缺点有:
1)由于弱学习器之间存在依赖关系,难以并行训练数据。不过可以通过自采样的SGBT来达到部分并行。
首先看下回归树即h(x)的生成
对于回归树算法来说最主要的是寻找最佳的划分点,那么回归树中的可划分点包含了所有特征的所有可取的值。在分类树中最佳划分点的判别标准是熵或者基尼系数,都是用纯度来衡量的。
但是在回归树中的样本标签也是连续数值,所以再使用熵之类的指标不再合适,取而代之的是平方误差,它能很好的评判数据分散程度
我们希望最佳划分节点能够使得划分得到的两组数据组内的标签值相近,如果每组的方差都很小,这就说明每组的组内相似度很高,确实应该被划分
算法流程
1.初始化弱分类器:
2.对迭代轮数有:
a.对每个样本计算负梯度,即残差 :
b.将上步得到的残差作为样本新的真实值,并将数据作为下棵树的训练数据,得到一颗新的回归树,其对应的叶子节点区域为,其中J为回归树 t 的叶子节点的个数
c.对叶子区域计算最佳拟合值:
d.更新强学习器:
3.得到强学习器:
由于此时只有根节点,样本1,2,3,4都在根节点,此时要找到使得平方损失函数最小的参数γ,怎么求呢?平方损失显然是一个凸函数,直接求导,倒数等于零,得到γ:
所以初始化时,γ取值为所有训练样本标签值的均值。γ=(1.1+1.3+1.7+1.8)/4=1.475,此时得到初始学习器:f0(x)=γ=1.475
2.对迭代轮数m=1m=1:
a.对每个样本i=1,2,...,Ni=1,2,...,N计算负梯度,即残差 :
b.将上步得到的残差作为样本新的真实值,并将数据作为下棵树的训练数据,得到一颗新的回归树f1(x),其对应的叶子节点区域为,其中J为回归树t的叶子节点的个数(这里J=2)
接着,寻找回归树的最佳划分节点,遍历每个特征的每个可能取值。从年龄特征的5开始,到体重特征的70结束,分别计算方差,找到使方差最小的那个划分节点即为最佳划分节点。
例如:以年龄7为划分节点,将小于7的样本划分为一类,大于等于7的样本划分为另一类。样本1为一组,样本2,3,4为一组,两组的方差分别为0,0.047,两组方差之和为0.047。所有可能划分情况如下表所示
以上划分点是的总方差最小为0.0125有两个划分点:年龄21和体重60,所以随机选一个作为划分点,这里我们选年龄21。 此时还需要做一件事情,给这两个叶子节点分别赋一个参数,来拟合残差。
c.对叶子区域j=1,2,...,Jj=1,2,...,J计算最佳拟合值(计算叶子结点的残差均值作为分支节点的值):
这里其实和上面初始化学习器是一个道理,平方损失,求导,令导数等于零,化简之后得到每个叶子节点的参数γ,其实就是标签值的均值。 根据上述划分节点:
样本3,4为右叶子节点,,所以
d.更新强学习器(加法模型):
此时可以获得每个样本在下轮循环M=2时的值,即将得到的残差作为样本新的真实值,参与到下一颗回归树的构建,如下:
3.对迭代轮数m=1,2,...,Mm=1,2,...,M,循环迭代M次,M是人为控制的参数,迭代结束生成M棵树
4.得到最后的强学习器:
为了方别展示和理解,我们假设M=1,根据上述结果得到强学习器:
5.预测样本5:
样本5在根节点中(即初始学习器)被预测为1.475,样本5的年龄为25,大于划分节点21岁,所以被分到了右边的叶子节点,同时被预测为0.275。此时便得到样本5的最总预测值为1.75。
GBDT用于分类仍然是采用回归树,但是由于样本输出不是连续的值,而是离散的类别,导致我们无法直接从输出类别去拟合类别输出的误差。为了解决这个问题,主要有两个方法,一个是用指数损失函数,此时GBDT退化为Adaboost算法。另一种方法是用类似于逻辑回归的对数似然损失函数的方法。也就是说,我们用的是类别的预测概率值和真实概率值的差来拟合损失。本文仅讨论用对数似然损失函数的GBDT分类。而对于对数似然损失函数,我们又有二元分类和多元分类的区别。
对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:
其中。则此时的负梯度误差为
对于生成的决策树,我们各个叶子节点的最佳残差拟合值为
由于上式比较难优化,我们一般使用近似值代替
除了负梯度计算和叶子节点的最佳残差拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。
(1)多元GBDT要比二元GBDT复杂一些,对应的是多元逻辑回归和二元逻辑回归的复杂度差别。假设类别数为K,则此时我们的对数似然损失函数为:
(2)其中如果样本输出类别为k,则。第k类的概率的表达式为:
(3)集合上两式,我们可以计算出第 t 轮的第 i 个样本对应类别 l 的负梯度误差为
观察上式可以看出,其实这里的误差就是样本 i 对应类别 l 的真实概率和 t−1 轮预测概率的差值。
(4)对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为
由于上式比较难优化,我们一般使用近似值代替
除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,多元GBDT分类和二元GBDT分类以及GBDT回归算法过程相同。
(1)针对样本 X 每个可能的类都训练一个分类回归树,得到k棵回归树。转换k分类问题,进行one-hot编码,由此每个样本标签值为k维向量[ 0,0,1,...0],其中位置为1的位置为该样本所属类别。
(2)初始化,即,,
(5)选取分裂节点及分裂阈值,根据阈值将样本划分为 大于等于feature 以及 小于 feature两部分。
实质上是CART树的生成过程。生成的关键问题:
- 哪个特征最合适?
- 是这个特征的什么特征值作为切分点?
对于问题2,通常是遍历所有的可能性,找到一个最好的特征和它对应的最优特征值可以让当前式子的值最小。
就以上面这个表利用残差找到一个最佳分类点,比如我们选s=31为分类点,则小于31的子树的均值为,大于等于31的子树的均值,则残差等于属于左子树样本的加上属于右子树样本的,最后得到31为最佳分类点,m(31)=1.42857。
1)随机森林采用的bagging思想,而GBDT采用的boosting思想。这两种方法都是Bootstrap思想的应用,Bootstrap是一种有放回的抽样方法思想。虽然都是有放回的抽样,但二者的区别在于:Bagging采用有放回的均匀取样,而Boosting根据错误率来取样(Boosting初始化时对每一个训练样例赋相等的权重1/n,然后用该算法对训练集训练t轮,每次训练后,对训练失败的样例赋以较大的权重),因此Boosting的分类精度要优于Bagging。Bagging的训练集的选择是随机的,各训练集之间相互独立,弱分类器可并行,而Boosting的训练集的选择与前一轮的学习结果有关,是串行的。
2)组成随机森林的树可以是分类树,也可以是回归树;而GBDT只能由回归树组成。
3)组成随机森林的树可以并行生成;而GBDT只能是串行生成。
4)对于最终的输出结果而言,随机森林采用多数投票等;而GBDT则是将所有结果累加起来,或者加权累加起来。
5)随机森林对异常值不敏感;GBDT对异常值非常敏感。
6)随机森林对训练集一视同仁;GBDT是基于权值的弱分类器的集成。
7)随机森林是通过减少模型方差提高性能;GBDT是通过减少模型偏差提高性能。
Xgboost是GB算法的高效实现,xgboost中的基学习器除了可以是CART(gbtree)也可以是线性分类器(gblinear)。下面所有的内容来自原始paper,包括公式。
(1) xgboost在目标函数中显示的加上了正则化项,基学习为CART时,正则化项与树的叶子节点的数量T和叶子节点的值有关。
(2) GB中使用Loss Function对f(x)的一阶导数计算出伪残差用于学习生成fm(x),xgboost不仅使用到了一阶导数,还使用二阶导数。
第t次的loss:
对上式做二阶泰勒展开:g为一阶导数,h为二阶导数
(3) 上面提到CART回归树中寻找最佳分割点的衡量标准是最小化均方差,xgboost寻找分割点的标准是最大化增益,lamda,gama与正则化项相关
xgboost算法的步骤和GB基本相同,都是首先初始化为一个常数,gb是根据一阶导数ri,xgboost是根据一阶导数gi和二阶导数hi,迭代生成基学习器,相加更新学习器。
xgboost与gdbt除了上述三点的不同,xgboost在实现时还做了许多优化,具体见下一个问题中XGBOOST优缺点
Xgboost:
优缺点:
适用场景:分类回归问题都可以。
Rf随机森林:
优点:
缺点:
1)随机森林在解决回归问题时,并没有像它在分类中表现的那么好,这是因为它并不能给出一个连续的输出。当进行回归时,随机森林不能够做出超越训练集数据范围的预测,这可能导致在某些特定噪声的数据进行建模时出现过度拟合。(PS:随机森林已经被证明在某些噪音较大的分类或者回归问题上回过拟合)。2)对于许多统计建模者来说,随机森林给人的感觉就像一个黑盒子,你无法控制模型内部的运行。只能在不同的参数和随机种子之间进行尝试。3)可能有很多相似的决策树,掩盖了真实的结果。4)对于小数据或者低维数据(特征较少的数据),可能不能产生很好的分类。(处理高维数据,处理特征遗失数据,处理不平衡数据是随机森林的长处)。5)执行数据虽然比boosting等快(随机森林属于bagging),但比单只决策树慢多了。
适用场景:数据维度相对低(几十维),同时对准确性有较高要求时。因为不需要很多参数调整就可以达到不错的效果,基本上不知道用什么方法的时候都可以先试一下随机森林。
Lr:
优点:实现简单,广泛的应用于工业问题上;分类时计算量非常小,速度很快,存储资源低;便利的观测样本概率分数;对逻辑回归而言,多重共线性并不是问题,它可以结合L2正则化来解决该问题。
缺点:当特征空间很大时,逻辑回归的性能不是很好;容易欠拟合,一般准确度不太高
不能很好地处理大量多类特征或变量;只能处理两分类问题(在此基础上衍生出来的softmax可以用于多分类),且必须线性可分;对于非线性特征,需要进行转换。
适用场景:LR同样是很多分类算法的基础组件,它的好处是输出值自然地落在0到1之间,并且有概率意义。因为它本质上是一个线性的分类器,所以处理不好特征之间相关的情况。虽然效果一般,却胜在模型清晰,背后的概率学经得住推敲。它拟合出来的参数就代表了每一个特征(feature)对结果的影响。也是一个理解数据的好工具。
(1)xgboost采用的是level-wise的分裂策略,而lightGBM采用了leaf-wise的策略,区别是xgboost对每一层所有节点做无差别分裂,可能有些节点的增益非常小,对结果影响不大,但是xgboost也进行了分裂,带来了务必要的开销。 leaft-wise的做法是在当前所有叶子节点中选择分裂收益最大的节点进行分裂,如此递归进行,很明显leaf-wise这种做法容易过拟合,因为容易陷入比较高的深度中,因此需要对最大深度做限制,从而避免过拟合。
(2)lightgbm使用了基于histogram的决策树算法,这一点不同与xgboost中的 exact 算法,histogram算法在内存和计算代价上都有不小优势。1)内存上优势:很明显,直方图算法的内存消耗为(#data* #features * 1Bytes)(因为对特征分桶后只需保存特征离散化之后的值),而xgboost的exact算法内存消耗为:(2 * #data * #features* 4Bytes),因为xgboost既要保存原始feature的值,也要保存这个值的顺序索引,这些值需要32位的浮点数来保存。2)计算上的优势,预排序算法在选择好分裂特征计算分裂收益时需要遍历所有样本的特征值,时间为(#data),而直方图算法只需要遍历桶就行了,时间为(#bin)
(3)直方图做差加速,一个子节点的直方图可以通过父节点的直方图减去兄弟节点的直方图得到,从而加速计算。
(4)lightgbm支持直接输入categorical 的feature,在对离散特征分裂时,每个取值都当作一个桶,分裂时的增益算的是”是否属于某个category“的gain。类似于one-hot编码。
(5)xgboost在每一层都动态构建直方图,因为xgboost的直方图算法不是针对某个特定的feature,而是所有feature共享一个直方图(每个样本的权重是二阶导),所以每一层都要重新构建直方图,而lightgbm中对每个特征都有一个直方图,所以构建一次直方图就够了。
其适用场景根据实际项目和两种算法的优点进行选择。
参考吃透GBDT(2019-05-26)
参考文献:
1. GBDT(MART) 迭代决策树入门教程 | 简介
2.GBDT原理与Sklearn源码分析-回归篇
3. 一步一步理解GB、GBDT、xgboost
4. 梯度提升树(GBDT)原理小结
5. 集成学习——Boosting之提升树(Boosting tree)、梯度提升树(GBDT)、XGBoost
6. GBDT
7. 吃透GBDT(2019-05-26)
8. 机器学习算法GBDT的面试要点总结-上篇