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.我们看一个 ...
随机推荐
- sqlserver2008的sql语句支持的最大长度
想写一个sql语句,很长,主要是in后跟着无数个用户ID,(虽然实现方式很低级,但是还是凑合着用吧) 不知道sql最大长度是多少,看了 SQL Server 的最大容量规范,写的是 包含 SQL 语句 ...
- Django框架(九):视图(二) HttpRequest对象、HttpResponse对象
1. HttpRequest对象 服务器接收到http协议的请求后,会根据报文创建HttpRequest对象,这个对象不需要我们创建,直接使用服务器构造好的对象就可以.视图的第一个参数必须是HttpR ...
- jQuery如何给DOM添加ID
ID每个元素只能有一个,ID名同一页面也不能重复,addID方法是不需要的,和其他属性一样用attr方法就行了, $(singleTarget).attr('id','idName'); 更简单的 $ ...
- drf序列化单改-整改-局部改-群改接口的实现
整体单改 路由层.模型层.序列化层不需要做修改,只需要处理视图层:views.py """ 1) 单整体改,说明前台要提供修改的数据,那么数据就需要校验,校验的数据应该在 ...
- MySql索引机制
第一部分 MySQL数据库索引的数据结构及算法理论 第二部分 MySQL索引实现机制 第三部分 MySQL中高性能使用索引的策略 数据结构及算法 MySQL官方对索引的定义为:索引(Index)是帮助 ...
- Python操作redis总结
安装模块及配置 首先安装redis,在Ubuntu下输入指令pip install redis即可.下载完成后,cd到指定目录下,打开指定文件,如下图所示: 输入密码打开后,修改指定地方的内容,与上篇 ...
- 2019CSP-J游记
2019-10-19:开一个坑,今天初赛,我是我们考场唯一几个坚持到16:45收卷的人,我们是机试,竟然可以用编译器. 这次初赛总体感觉打得不错,卷面满分200,最后实际分数,就是卷面分除以二. 初赛 ...
- Java集合详解(全)
Java的集合主要有List , Set, Map List , Set继承至Collection接口,Map为独立接口 List下有ArrayList,LinkedList,Vector Set下有 ...
- Python笔记_第四篇_高阶编程_py2与py3的区别
1. 性能: py3.x起始比py2.x效率低,但是py3.x现有极大的优化空间,效率正在追赶. 2. 编码: py3.x原码文件默认使用的utf-8编码,使得变量名更为宽阔. 3. 语法: * 去除 ...
- rare alleles
I.4 Where the rare alleles are found p是基因A的频率,N是个体数目(也就是基因型个数,所以基因个数是2n,所以全部个体的基因A的个数是2np),p方是PAA,np ...