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$的子树剪掉。

参考资料:

  1. Introduction to Boosted Trees by 陈天奇
  2. A Discussion on GBDT: Gradient Boosting Decision Tree by Tom
  3. A Gentle Introduction to Gradient Boosting by Cheng Li

GBDT的理解和总结的更多相关文章

  1. [Machine Learning & Algorithm] 决策树与迭代决策树(GBDT)

    谈完数据结构中的树(详情见参照之前博文<数据结构中各种树>),我们来谈一谈机器学习算法中的各种树形算法,包括ID3.C4.5.CART以及基于集成思想的树模型Random Forest和G ...

  2. GBDT原理详解

    从提升树出发,——>回归提升树.二元分类.多元分类三个GBDT常见算法. 提升树 梯度提升树 回归提升树 二元分类 多元分类 面经 提升树 在说GBDT之前,先说说提升树(boosting tr ...

  3. GBDT 总结文档

    在做阿里的o2o优惠券预测的时候学习了GBDT.听闻GBDT的威力,自然要学习学习. 接下来从以下几个方面记录下我对于GBDT的理解. GBDT的用途,优势 GBDT的结构和算法流程 GBDT如何训练 ...

  4. GBDT 算法

    GBDT (Gradient Boosting Decision Tree) 梯度提升迭代决策树.GBDT 也是 Boosting 算法的一种,但是和 AdaBoost 算法不同(AdaBoost 算 ...

  5. 一步一步理解GB、GBDT、xgboost

    GBDT和xgboost在竞赛和工业界使用都非常频繁,能有效的应用到分类.回归.排序问题,虽然使用起来不难,但是要能完整的理解还是有一点麻烦的.本文尝试一步一步梳理GB.GBDT.xgboost,它们 ...

  6. (转)GBDT迭代决策树理解

    在网上看到一篇对从代码层面理解gbdt比较好的文章,转载记录一下: GBDT(Gradient Boosting Decision Tree) 又叫 MART(Multiple Additive Re ...

  7. gbdt xgboost 贼难理解!

    https://www.zybuluo.com/yxd/note/611571 https://zhuanlan.zhihu.com/p/29765582 gbdt 在看统计学习方法的时候 理解很吃力 ...

  8. GBDT理解

    一.提升树 提升方法实际采用加法模型(即基函数的线性组合)与前向分布算法.以决策树为基函数的提升方法称为提升树,boosting tree.对分类问题的决策树是二叉分类树,对回归问题的决策树是二叉回归 ...

  9. 大白话5分钟带你走进人工智能-第31节集成学习之最通俗理解GBDT原理和过程

    目录 1.前述 2.向量空间的梯度下降: 3.函数空间的梯度下降: 4.梯度下降的流程: 5.在向量空间的梯度下降和在函数空间的梯度下降有什么区别呢? 6.我们看下GBDT的流程图解: 7.我们看一个 ...

随机推荐

  1. 正文内容 python3编码问题

    来源:http://www.jb51.net/article/92006.htm 以下是全文: 这两天写了个监测网页的爬虫,作用是跟踪一个网页的变化,但运行了一晚出现了一个问题....希望大家不吝赐教 ...

  2. CodeForces-1100C NN and the Optical Illusion 简单数学

    题目链接:https://vjudge.net/problem/CodeForces-1100C 题意: 题目给出外部圆的数目n和内部圆的半径r,要求求出外部圆的半径以满足图片要求. 显然这是一道数学 ...

  3. shell的一些一句话东西

    shell的一些一句话东西 2010-09-10 11:22:58|  分类: linux shell |  标签:shell  linux  |举报|字号 订阅     time -p [程序] 可 ...

  4. HashMap源码分析(一)

    基于JDK1.7 HashMap源码分析 概述 HashMap是存放键值对的集合,数据结构如下: table被称为桶,大小(capacity)始终为2的幂,当发生扩容时,map容量扩大为两倍 Hash ...

  5. FPGA的基本组成单元LUT,以及三种核的概念

    .查找表 LUT就是查找表,对于4输入的LUT而言,实际上就是4位地址位,一位数据位的存储器,能够存储16位数据,所以我们在FPGA设计中可以用LUT组建分布式的RAM. 这样也可以解释我们在设计中为 ...

  6. 201604-1 折点计数 Java

    思路: 这个题要小心考虑不全.左右两边都比这个数小 或者 左右两边都比这个数大 import java.util.Scanner; public class Main { public static ...

  7. Struts 2的流程

    Struts 2的流程 一.Struts 2 的开发步骤: 在web.xml中定义核心的Filter来拦截用户的请求. 由于Web应用时基于请求/响应架构的应用,所以不管哪个MVC Web框架,都需要 ...

  8. 第1章 分布式系统概念与ZooKeeper简介

    ZooKeeper分布式专题与Dubbo微服务入门 第1章 分布式系统概念与ZooKeeper简介 1-1 zookeeper简介 1-2 什么是分布式系统 略 1-3 分布式系统的瓶颈以及zk的相关 ...

  9. ZJNU 1542 - 三角形(续)--中高级

    从小到大排序后 先固定一遍,另外两边递增查找 即固定 i,j=i+1,k=j+1 然后让k递增到 a[i]+a[j]<=a[k] 时 此时不能凑成一个三角形 答案增加 k-1-j 组 此时不需要 ...

  10. win10环境下pyinstaller打包pytorch遇到的问题及解决方案

    pytorch-python源码生成windows的应用程序(.exe),报错OSError: could not get source code Failed to execute script h ...