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.我们看一个 ...
随机推荐
- VMware DRS部分知识点
主机添加到集群中,不需要维护模式(有虚拟机开机状态时也可以添加进去). 主机从集群中移除,需要主机进入维护模式. HA和DRS 全自动 当设置虚拟机必须在主机上时 DRS优先级大于HA 就算主机挂了H ...
- es和数据库关系对比
es类比传统关系型数据库: Relational DB -> Databases -> Tables -> Rows -> Columns Elasticsearch -& ...
- 吴裕雄--天生自然 PYTHON3开发学习:数字(Number)
print ("abs(-40) : ", abs(-40)) print ("abs(100.10) : ", abs(100.10)) #!/usr/bin ...
- druid socket timeout超时15分钟(转载)
背景 在应用端通过mybatis的interceptor自定义Plugin拦截Executor, 统计输出sql的执行耗时. 今天生产发生一个很奇怪的问题: 莫名其妙卡顿15分钟+,其后正常返回sql ...
- lightgbm直方图算法
https://blog.csdn.net/anshuai_aw1/article/details/83040541
- Go-简介-发展
01-Go语言介绍 目录 Go语言介绍 Go语言特性 Go语言发展(版本/特性) Go语言应用 谁在用 应用领域 Go语言项目 Go语架构 Go语言发展前景 Go语言介绍 Go 即Golang,是Go ...
- python3拆包详解
对于可迭代对象,如元组.列表.字符串.集合.字典这些可迭代对象都可以被拆包,拆包是指将一个结构中的数据拆分为多个单独变量中.拆包的方式大致有两种,一种是以变量的方式来接收,另一种是用'*'号.下面先讲 ...
- 学习spring第一天
Spring第一天笔记 1. 说在前面 怎样的架构的程序,我们认为是一个优秀的架构? 我们考虑的标准:可维护性好,可扩展性好,性能. 什么叫可扩展性好? 答:就是可以做到,不断的增加代码,但是可以 ...
- 九、Shell脚本高级编程实战第九部
一.监控mysql主从同步是否异常,如果异常,发送短信给管理员 1)开发一个守护进程脚本每30秒实现检测一次. 2)如果错误号是:1158.1159.1008.1007.1062,请跳过 3)请使用数 ...
- Mac电脑没声音了怎么办?苹果电脑没声音的解决方法
在使用Mac电脑的过程中,偶尔会出现电脑没声音?发出奇怪的声音?连接外部音频设备出问题等音频故障,遇到这种情况该怎么办呢?小编有妙招! 检查音量 首先检查Mac是否被静音,按住F12快捷键或滑动菜单栏 ...