GBDT的理解和总结
2015/11/21 16:29:29 by guhaohit
导语:
GBDT是非常有用的机器学习的其中一个算法,目前广泛应用于各个领域中(regression,classification,ranking)。这篇文章是我自己对GBDT的总结加上自己的一些理解,所以中间一些内容并不全都是个人的原创。由于自身水平有限,可能会有错误,主要是为了让自己加强对GBDT的理解。
一,GBDT简介:
GBDT的中文名叫做梯度提升决策树。由名字我们就可以看出,这个算法是由两部分构成的,梯度提升和决策树,而GBDT就是用简单决策树作为基分类器的梯度提升方法。
对于决策树,在这里不多做介绍,树形结构,建立决策树的关键,即在当前状态下选择哪个属性作为分类依据。根据不同的目标函数,建立决策树主要有三种算法:ID3,C4.5和CART。具体内容可以参考@李航老师的《统计学习方法》。接下来我将重点说一说梯度提升。
二,梯度提升:
Gradient Boosting = Gradient Descent + Boosting
梯度提升其实就是一种提升方法(Boosting)。我们最熟悉的应用boosting的算法就是Adaboost了,利用多个弱分类器,通过加法模型(ensemble)的方式组合起来,得到效果不错的分类器。为了更好的理解boosting这个方法,我想先介绍前向分步算法,然后再来介绍梯度提升。
1. 前向分布算法
先说结论:Adaboost算法可以理解为加法模型(additive model)、损失函数为指数函数、学习算法为前向分布算法的二类分类学习算法。
下面给出加法模型的表达式:
$$H(x) = sum_{t}{rho_{t}h_t(x)}$$
其中 $t$ 表示弱分类器的数量,$h_t(x)$表示弱分类器,$rho_{t}$表示该弱分类器的权重。
简单来说,前向分布算法就是在多轮迭代中,每次引入一个弱分类器来弥补我们已有的分类器的缺陷。
在Adaboost算法中,我们定义缺陷为高权重的数据。我们生成的新弱分类器优先将高权重的数据拟合,而将拟合的好的数据的权重降低,将拟合的不好的数据的权重提高,从而在下个弱分类器中能更重视这些分错的数据。
2. Boost方法
对于一个问题,如果存在一个多项式的学习算法能学习,并且正确率很高,那么就称为强可学习的;如果正确率仅比随机猜测略好,则称为弱可学习的。在PAC (probably approximately correct)学习框架下,强可学习与弱可学习是等价的。
对于一个分类问题,我们存在两种类型的分类器:强分类器和弱分类器,相对于强分类器,弱分类器更容易得到。这样一来,如果我们已经得到了“弱学习算法”,那么我们能否将它提升(boost)为“强学习算法”。
对于提升算法而言,有两个问题需要解决:1.找到当前弱分类器的缺陷。2.将弱分类器组合起来,弥补缺陷,得到一个强分类器。
对于Adaboost算法来说,找到弱分类器的缺陷为错分的数据,通过改变数据的权值并采用加权投票的方式来弥补缺陷。
3. 梯度提升(Gradient Boosting)
这里我解释梯度提升为利用梯度下降的思想,通过拟合梯度的方法来将弱分类器提升为强分类器。
在Gradient Boosting算法中,我们定义缺陷为梯度。有可能会有疑问,为什么可以把梯度定义为缺陷呢?先来回顾下梯度下降的概念:
$$theta_{i}:=theta_{i}-rho frac{partial{J}}{partial{theta_{i}}}$$
将$f(x)$泰勒展开$f(x+varepsilon)=f(x)+frac{partial{f(x)}}{partial{x}}varepsilon +O(x^2)$,我们想让$f(x+varepsilon)-f(x)<0$,即$frac{partial{f(x)}}{partial{x}}varepsilon <0$,所以我们取$varepsilon = -frac{partial{f(x)}}{partial{x}}$使得$frac{partial{f(x)}}{partial{x}}varepsilon $最小,所以梯度下降又被称为最速梯度下降法。
假设我们的模型为$F(x)$,Loss function为$L(y,F(x))=sum_{i}{L(y_{i},F(x_i))}$,我们需要调整$F(x_i)$使得Loss function最小。我们将$F(x_i)$当作之前的参数$theta_i$求偏导$frac{partial{L(y_{i},F(x_i))}}{partial{F(x_i)}}$,然后我们需要做的就是更新参数:
$$F_{new}(x_i) = F(x_i)-rho times frac {partial{L(y_{i},F(x_i))}}{partial{F(x_i)}} $$
上式中,$x_i$表示一个样本点,对于训练集中的所有点,都满足上式。请注意一点,这里的$F(x)$是我们的模型,我们通过一次迭代,得到了一个新的模型,由梯度下降的定理来说,这个新的$F(x)$对于训练集上的所有的点,使得我们的Loss function更小。
到此为止,我们得到了一个惊喜的发现,我们找到了公式,能使得我们的模型变的更好。现在我们需要解决的就是,将所求得的梯度值拟合出来。后面的事很容易想到,我们使用决策树来拟合这个梯度,得到新的公式:
$$F_{n+1}(x) = F_{n}(x) + eta times T_{n+1}(x)$$
其中$T_{n+1}$表示的通过拟合$F_{n}(x)$的梯度得到的决策树,$eta$可以看成是$-rho$。
4. 梯度提升应用于回归问题
对于梯度提升方法,可以应用于regression,classification,ranking等多个方面,而难度也是逐渐增加。
对于回归问题,由之前的分析,很容易给出相对应算法:
give any differentiable loss function L:
start with an initial model, set $F(x) =frac{sum_{i=1}^{n}{y_i}}{n}$
iterate until converge:
calculate negative gradients $-g(x_i)=-frac {partial{L(y_{i},F(x_i))}}{partial{F(x_i)}}$
fit a regression tree h to negative gradients $-g(x_i)$
$F:=F+rho h$
其中$rho$可以采用求极值的方式进行求解,使得Loss function最小。
对于机器学习算法来说都会存在过拟合的问题,如果我们得到的拟合梯度的决策树太复杂或者树的个数过多的话,容易出现过拟合的现象,我们将采用正 大专栏 GBDT的理解和总结则化的方法来保证我们的模型不会过拟合。
可以采用CART剪枝的方法来对每次的生成树进行控制,并且加入正则项$lambda |T|$,其中$|T|$表示当前已有的树的数目,也可以将T当成参数来调整。
在实际项目中,经常用到一种叫做shrinkage
的方法,就是它不完全信任每一个棵拟合梯度的树,它认为每棵树只学到了真理的一小部分,累加的时候只累加一小部分,通过多学几棵树弥补不足。用方程来看更清晰,即:
$$F_{n+1}(x)=F_{n}(x)+upsilon times eta T_{n+1}(x)$$
一个有趣的现象就是当$upsilon$越小时,$|T|$的值越大,这些值都可以当做参数在验证集中调整。shrinkage
方法在实际应用中非常有效,但是目前缺少相应的理论证明。
5. 梯度提升应用于分类问题
假设我们要将数据分为$K$类,我们建立$K$个模型$F_{1}(x),F_{2}(x),…F_{K}(x)$,采用信息熵的思想,我们转化成概率值:
$$P_{i}(x)=frac {e^{F_{i}(x)}}{sum_{c=1}^{K}{e^{F_{c}(x)}}}$$
上式代表了当前数据x于第i类的概率值。对于每一个数据,可得到$P(x)=[P_{1}(x),P_{2}(x),…P_{K}(x)]$,假设这个数据属于第j类,那么$Y=[0,…,1,…,0]$,我们建立Loss function为$L(P(x),Y)$,有很多这样的函数,比如softmax回归的目标函数和KL-divergence。
接下来就跟之前说的回归问题的解法一样了,唯一的区别就是我们每次要得到K棵树来更新K个模型。
三. 梯度提升的进阶
前面说的梯度提升的方法是通过拟合梯度,而梯度由泰勒展开推导出来的,能否能利用Loss function的二阶导数呢?
我们直接从Loss function的泰勒展开开始:
$$begin{split}
L(y,F_{n}(x))&=sum_{i}{L(y_{i},F_{n}(x_i))}\
&=sum_{i}{L(y_{i},F_{n-1}(x_i)+T_{n}(x_{i}))}\
&=sum_{i}left[ { L(y_{i},F_{n-1}(x_i))} + g_{i}^{n-1}T_{n}(x_i)+frac{1}{2}h_{i}^{n-1}T_{n}^2(x_i)right]
end{split}$$
其中,$g_{i}^{n-1}=frac{partial{L(y_{i},F_{n-1}(x_i))}}{partial{F_{n-1}(x_i)}}$,$h_{i}^{n-1}=frac{partial^{2}{L(y_{i},F_{n-1}(x_i))}}{partial^{2}{F_{n-1}(x_i)}}$。
很容易得到:
$$L(y,F_{n}(x))-L(y,F_{n-1}(x))=sum_{i}left[ g_{i}^{n-1}T_{n}(x_i)+frac{1}{2}h_{i}^{n-1}T_{n}^2(x_i)right]$$
很容易得到,当$T_{n}(x_{i})=-frac{g_{i}^{n-1}}{h_{i}^{n-1}}$时,能使得上式左边最小,即$L(y,F_{n}(x))-L(y,F_{n-1}(x))=sum_{i}left[ -frac{(g_{i}^{n-1})^2}{2h_{i}^{n-1}}right]$,只有当$h_{i}^{n-1}>0$的时候才能满足。再回过头看一看$h_{i}^{n-1}$的定义,它是我们Loss function关于$F(x)$的二阶偏导,当Loss function是下凸函数时,能满足$h_{i}^{n-1}>0$这个条件。细心的人应该已经发现了,其实这个就是牛顿法的变形。接下来我们只需要用决策树来拟合$-frac{g_{i}^{n-1}}{h_{i}^{n-1}}$就好了。
之后看来@陈天奇怪同学写的关于GBDT的文章,看到他讲解了引入正则化的方法,而且xgboost也是用的这种方式进行的实现。
我们对目标式子中加入正则化(对生成的树进行限制):
$$begin{split}
Obj^{(n)}&=L(y,F_{n}(x))-L(y,F_{n-1}(x))\
&=sum_{i}left[ g_{i}^{n-1}T_{n}(x_i)+frac{1}{2}h_{i}^{n-1}T_{n}^2(x_i)right]+Omega left( T_{n} right)
end{split}$$
我们先来定义树的结构,假设生成的树有M个叶子节点,每一个x最后会投影到其中一个叶子节点上,我们定义这个投影为$q(x): mathscr{R}^drightarrow { { 1,2,…,M }}$,每个叶子节点的输出值为$w_{1},w_{2},…,w_{M}in mathscr{R}$,我们生成的树为:$T_{n}(x)=w_{q(x)}$。
而对于正则化项,我们这样定义:$Omega left( T_{n} right)=gamma M+frac{1}{2}lambda sum_{j=1}^{M}{w_{j}^2}$。正则化项分为两部分,叶子节点数目和叶子节点的输出值,这不是正则化项的唯一定义形式,我这用的是@陈天奇怪ppt中的方法。
$$begin{split}
Obj^{(n)}&=sum_{i}left[ g_{i}^{n-1}T_{n}(x_i)+frac{1}{2}h_{i}^{n-1}T_{n}^2(x_i)right]+Omega left( T_{n} right) \
&=sum_{i}left[ g_{i}^{n-1}T_{n}(x_i)+frac{1}{2}h_{i}^{n-1}T_{n}^2(x_i)right]+gamma M+frac{1}{2}lambda sum_{j=1}^{M}{w_{j}^2} \
&=sum_{j=i}^{M}left[ left(sum_{iin I_{j}}{g_{i}^{n-1}} right)w_{j}+
frac{1}{2}left( sum_{iin I_{j}}{h_{i}^{n-1}+lambda} right)w_{j}^2 + gamma Mright] \
&=sum_{j=i}^{M}left[ G_{j}w_{j}+
frac{1}{2}left( H_{j}+lambda right) w_{j}^2 + gamma Mright]
end{split}$$
上式中,$I_{j}$表示j叶子节点中样本的集合,$I_{j}={ i ,|, q(x_{i}=j)}$。$G_{j}=sum_{iin I_{j}}{g_{i}^{n-1}}$,$H_{j}=sum_{iin I_{j}}{h_{i}^{n-1}}$。
现在我们对于每一个叶子节点,$w_j=-frac{G_{j}}{H_{j}+lambda}$时能得到最小值,最小值为$-frac{1}{2}sum_{j=1}^{M}{frac{G_{j}^2}{H_{j}+lambda}+gamma M}$。
最后说一说这种方法的生成树的方法,将数据集合按照决策树的方法进行分裂(split),但是我们定义一种新的分裂标准:
$$Gain = frac{G_{L}^2}{H_{L}+lambda}+frac{G_{R}^2}{H_{R}+lambda}-frac{left( G_{L}+G_{R}right)^2}{ H_{L}+H_{R}+lambda}-gamma$$
这表示把一棵树的一个结点分裂成两棵子树后Loss function减小的值,我们找到$Gain$最大的分裂方法即可。
我们可以看到,我们要求$H_{j}+lambda>0$,对比于之前我们没有加入正则化项之前的要求,已经放松很多了,需要叶子节点所有的样本的二阶偏导之和大于$-lambda$即可。
我们还可以通过剪枝来优化我们的方法,生成树之后,从下往上,将$Gain<0$的子树剪掉。
参考资料:
- Introduction to Boosted Trees by 陈天奇
- A Discussion on GBDT: Gradient Boosting Decision Tree by Tom
- A Gentle Introduction to Gradient Boosting by Cheng Li
GBDT的理解和总结的更多相关文章
- [Machine Learning & Algorithm] 决策树与迭代决策树(GBDT)
谈完数据结构中的树(详情见参照之前博文<数据结构中各种树>),我们来谈一谈机器学习算法中的各种树形算法,包括ID3.C4.5.CART以及基于集成思想的树模型Random Forest和G ...
- GBDT原理详解
从提升树出发,——>回归提升树.二元分类.多元分类三个GBDT常见算法. 提升树 梯度提升树 回归提升树 二元分类 多元分类 面经 提升树 在说GBDT之前,先说说提升树(boosting tr ...
- GBDT 总结文档
在做阿里的o2o优惠券预测的时候学习了GBDT.听闻GBDT的威力,自然要学习学习. 接下来从以下几个方面记录下我对于GBDT的理解. GBDT的用途,优势 GBDT的结构和算法流程 GBDT如何训练 ...
- GBDT 算法
GBDT (Gradient Boosting Decision Tree) 梯度提升迭代决策树.GBDT 也是 Boosting 算法的一种,但是和 AdaBoost 算法不同(AdaBoost 算 ...
- 一步一步理解GB、GBDT、xgboost
GBDT和xgboost在竞赛和工业界使用都非常频繁,能有效的应用到分类.回归.排序问题,虽然使用起来不难,但是要能完整的理解还是有一点麻烦的.本文尝试一步一步梳理GB.GBDT.xgboost,它们 ...
- (转)GBDT迭代决策树理解
在网上看到一篇对从代码层面理解gbdt比较好的文章,转载记录一下: GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Re ...
- gbdt xgboost 贼难理解!
https://www.zybuluo.com/yxd/note/611571 https://zhuanlan.zhihu.com/p/29765582 gbdt 在看统计学习方法的时候 理解很吃力 ...
- GBDT理解
一.提升树 提升方法实际采用加法模型(即基函数的线性组合)与前向分布算法.以决策树为基函数的提升方法称为提升树,boosting tree.对分类问题的决策树是二叉分类树,对回归问题的决策树是二叉回归 ...
- 大白话5分钟带你走进人工智能-第31节集成学习之最通俗理解GBDT原理和过程
目录 1.前述 2.向量空间的梯度下降: 3.函数空间的梯度下降: 4.梯度下降的流程: 5.在向量空间的梯度下降和在函数空间的梯度下降有什么区别呢? 6.我们看下GBDT的流程图解: 7.我们看一个 ...
随机推荐
- vue组件传值 part2
非父子组件传值 轻量级 视图层框架 复杂组件间传值,引进其他的工具或者设计模式 1.vuex 2.总线机制 //main line 1.在main.js中注册全局的bus Vue.prototype. ...
- js判断苹果和安卓端或者wp端
最近做了一个H5,说要提供一个底部,可以区分安卓或者ios,到相应的网址进行下载APP,如图: 代码如下: window.onload = function () { var u = navigat ...
- ELK简单配置
input { file { path => ["/usr/local/kencery/tomcat/logs/catalina.out"] type => " ...
- js中要声明变量吗?
你好,js语言是弱类型语言,无需申明即可直接使用,默认是作为全局变量使用的.建议:在function里时应使用var 申明变量,这样改变量仅仅只在function的生存周期内存在,不会污染到,全局控件 ...
- 一个简单WebApp的全程
开始前,我先给出上一篇选项卡的demo链接http://xqhuadou.com/demo1/index.html.相信看着应该很带感,不过这个是之前经过修改的. 制作过程我就不多说了,可以直接看源码 ...
- NOIp2017TG解题报告
NOIp2018RP++! 虽然没去但还得写写QAQ D1T1 : 小凯的疑惑 数学题 手推几组数据然后发现规律 \(Ans = (a-1)(b-1)+1\) AC in 1minite D1T2 : ...
- 7)get方式提交表单和简单处理
一个带有html的代码: hello.php <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" ...
- Java字符串替换函数replace、replaceFirst、replaceAll
一.replace(String old,String new) 功能:将字符串中的所有old子字符串替换成new字符串 示例 String s="Hollow world!"; ...
- Codeforces 1293A - ConneR and the A.R.C. Markland-N
题目大意: ConneR老师想吃东西,他现在在大楼的第s层,大楼总共有n层,但是其中有k层的餐厅关门了. 然后给了这k层关门的餐厅分别所在的楼层. 所以问ConneR老师最少得往上(或者往下)走几层楼 ...
- Java/Oracle/mySQL 日期格式
Java: yyyy-MM-dd HH:mm:ss.SSS Oracel: yyyy-MM-dd HH24:mi:ss select * from to_pub_report where report ...