之前一篇文章简单地讲了XGBoost的实现与普通GBDT实现的不同之处,本文尝试总结一下GBDT运用的正则化技巧。

Early Stopping

Early Stopping是机器学习迭代式训练模型中很常见的防止过拟合技巧,维基百科里如下描述:

In machine learning, early stopping is a form of regularization used to avoid overfitting when training a learner with an iterative method, such as gradient descent.

具体的做法是选择一部分样本作为验证集,在迭代拟合训练集的过程中,如果模型在验证集里错误率不再下降,就停止训练,也就是说控制迭代的轮数(树的个数)。

XGBoost Python关于early stopping的参数设置文档非常清晰,API如下:

# code snippets from xgboost python-package training.py
def train(..., evals=(), early_stopping_rounds=None)
"""Train a booster with given parameters.
Parameters
----------
early_stopping_rounds: int
Activates early stopping. Validation error needs to decrease at least
every <early_stopping_rounds> round(s) to continue training.
"""

Sklearn的GBDT实现虽然可以添加early stopping,但是比较复杂。官方没有相应的文档和代码样例,必须看源码。实现的时候需要用户提供monitor回调函数,且要了解源码内部_fit_stages函数的locals,总之对新手很不友好:

#code snippets from sklearn.ensemble.gradient_boosting
class BaseGradientBoosting(six.with_metaclass(ABCMeta, BaseEnsemble,
_LearntSelectorMixin)):
"""Abstract base class for Gradient Boosting. """
...
def fit(self, X, y, sample_weight=None, monitor=None):
"""Fit the gradient boosting model.
Parameters
----------
monitor : callable, optional
The monitor is called after each iteration with the current
iteration, a reference to the estimator and the local variables of
``_fit_stages`` as keyword arguments ``callable(i, self,
locals())``. If the callable returns ``True`` the fitting procedure
is stopped. The monitor can be used for various things such as
computing held-out estimates, early stopping, model introspect, and
snapshoting.
"""

对Sklearn感兴趣的可以看这篇文章Using Gradient Boosting (with Early Stopping),里面有回调函数monitor的参考实现。

Shrinkage

Shrinkage就是将每棵树的输出结果乘一个因子(0<ν<10<ν<1),其中ΣJmj=1γjmI(x∈Rjm)Σj=1JmγjmI(x∈Rjm)是第m棵的输出,而f(m)f(m)是前m棵树的ensemble:

fm(x)=fm−1(x)+ν⋅ΣJmj=1γjmI(x∈Rjm)fm(x)=fm−1(x)+ν⋅Σj=1JmγjmI(x∈Rjm)

ESL书中这样讲:

The parameter νν can be regarded as controlling the leanring rate of the boosting procedure

νν和迭代轮数M(树个数)是一个tradeoff,推荐的是νν值设置小一点(如0.1),而M设置大一些。这样一般能有比较好的准确率,代价是训练时间变长(与M成比例)。

下面是Sklearn的实现关于该参数设置的片段,XGBoost类似:

#code snippets from sklearn.ensemble.gradient_boosting
class GradientBoostingClassifier(BaseGradientBoosting, ClassifierMixin):
"""Gradient Boosting for classification.""" def __init__(self, ..., learning_rate=0.1, n_estimators=100, ...):
"""
Parameters
----------
learning_rate : float, optional (default=0.1)
learning rate shrinks the contribution of each tree by `learning_rate`.
There is a trade-off between learning_rate and n_estimators.
n_estimators : int (default=100)
The number of boosting stages to perform. Gradient boosting
is fairly robust to over-fitting so a large number usually
results in better performance
"""

Subsampling

Subsampling其实源于bootstrap averaging(bagging)思想,GBDT里的做法是在每一轮建树时,样本是从训练集合中无放回随机抽样的ηη部分,典型的ηη值是0.5。这样做既能对模型起正则作用,也能减少计算时间。

事实上,XGBoost和Sklearn的实现均借鉴了随机森林,除了有样本层次上的采样,也有特征采样。也就是说建树的时候只从随机选取的一些特征列寻找最优分裂。 下面是Sklearn里的相关参数设置的片段,

#code snippets from sklearn.ensemble.gradient_boosting
class GradientBoostingClassifier(BaseGradientBoosting, ClassifierMixin):
"""Gradient Boosting for classification.""" def __init__(self, ..., subsample=1.0, max_features=None,...):
"""
Parameters
----------
subsample : float, optional (default=1.0)
The fraction of samples to be used for fitting the individual base
learners. If smaller than 1.0 this results in Stochastic Gradient
Boosting. `subsample` interacts with the parameter `n_estimators`.
Choosing `subsample < 1.0` leads to a reduction of variance
and an increase in bias.
max_features : int, float, string or None, optional (default=None)
The number of features to consider when looking for the best split:
"""

Regularized Learning Objective

将树模型的复杂度作为正则项显式地加进优化目标里,是XGBoost实现的独到之处。

L(t)=∑i=1nl(yi,y∗(t−1)i+ft(xi))+Ω(ft)L(t)=∑i=1nl(yi,yi∗(t−1)+ft(xi))+Ω(ft)

where

Ω(f)=γT+12λ||w||2Ω(f)=γT+12λ||w||2

其中y∗(t)iyi∗(t)是第t轮第i个instance的预测值,ftft是第t轮建的树,TT是树叶结点数目,ww是树叶结点的输出,γ,λγ,λ是正则化参数。深入了解加了正则后如何推导剃度更新的可以看XGBoost的论文

我个人的看法是将树模型的复杂度作为正则化项加在优化目标,相比自己通过参数控制每轮树的复杂度更直接,这可能是XGBoost相比普通GBDT实现效果更好的一个很重要的原因。很遗憾,Sklearn暂时无相应的实现。

Dropout

Dropout是deep learning里很常用的正则化技巧,很自然的我们会想能不能把Dropout用到GBDT模型上呢?AISTATS2015有篇文章DART: Dropouts meet Multiple Additive Regression Trees进行了一些尝试。

文中提到GBDT里会出现over-specialization的问题:

Trees added at later iterations tend to impact the prediction of only a few instances, and they make negligible contribution towards the prediction of all the remaining instances. We call this issue of subsequent trees affecting the prediction of only a small fraction of the training instances over-specialization.

也就是说前面迭代的树对预测值的贡献比较大,后面的树会集中预测一小部分样本的偏差。Shrinkage可以减轻over-specialization的问题,但不是很好。作者想通过Dropout来平衡所有树对预测的贡献,如下图的效果: 

具体的做法如下:

DART divergesfrom MART at two places. First, when computing the gradient that the next tree will fit, only a random subset of the existing ensemble is considered. The second place at which DART diverges from MART is when adding the new tree to the ensemble where DART performs a normalization step.

简单说就是每次新加一棵树,这棵树要拟合的并不是之前全部树ensemble后的残差,而是随机抽取的一些树ensemble;同时新加的树结果要规范化一下。

这种新做法对GBDT效果的提升有多明显还有待大家探索尝试。

Regularization on GBDT的更多相关文章

  1. 决策树和基于决策树的集成方法(DT,RF,GBDT,XGB)复习总结

    摘要: 1.算法概述 2.算法推导 3.算法特性及优缺点 4.注意事项 5.实现和具体例子 内容: 1.算法概述 1.1 决策树(DT)是一种基本的分类和回归方法.在分类问题中它可以认为是if-the ...

  2. GBDT和XGBOOST算法原理

    GBDT 以多分类问题为例介绍GBDT的算法,针对多分类问题,每次迭代都需要生成K个树(K为分类的个数),记为\(F_{mk}(x)\),其中m为迭代次数,k为分类. 针对每个训练样本,使用的损失函数 ...

  3. GBDT(Gradient Boosting Decision Tree) 没有实现仅仅有原理

                阿弥陀佛.好久没写文章,实在是受不了了.特来填坑,近期实习了(ting)解(shuo)到(le)非常多工业界经常使用的算法.诸如GBDT,CRF,topic model的一些算 ...

  4. 机器学习算法--GBDT

    转自 http://blog.csdn.net/u014568921/article/details/49383379 另外一个很容易理解的文章 :http://www.jianshu.com/p/0 ...

  5. 决策树与树集成模型(bootstrap, 决策树(信息熵,信息增益, 信息增益率, 基尼系数),回归树, Bagging, 随机森林, Boosting, Adaboost, GBDT, XGboost)

    1.bootstrap   在原始数据的范围内作有放回的再抽样M个, 样本容量仍为n,原始数据中每个观察单位每次被抽到的概率相等, 为1/n , 所得样本称为Bootstrap样本.于是可得到参数θ的 ...

  6. Spark2.0机器学习系列之6:GBDT(梯度提升决策树)、GBDT与随机森林差异、参数调试及Scikit代码分析

    概念梳理 GBDT的别称 GBDT(Gradient Boost Decision Tree),梯度提升决策树.     GBDT这个算法还有一些其他的名字,比如说MART(Multiple Addi ...

  7. 数据预处理中归一化(Normalization)与损失函数中正则化(Regularization)解惑

    背景:数据挖掘/机器学习中的术语较多,而且我的知识有限.之前一直疑惑正则这个概念.所以写了篇博文梳理下 摘要: 1.正则化(Regularization) 1.1 正则化的目的 1.2 正则化的L1范 ...

  8. scikit-learn 梯度提升树(GBDT)调参小结

    在梯度提升树(GBDT)原理小结中,我们对GBDT的原理做了总结,本文我们就从scikit-learn里GBDT的类库使用方法作一个总结,主要会关注调参中的一些要点. 1. scikit-learn ...

  9. 梯度提升树(GBDT)原理小结

    在集成学习之Adaboost算法原理小结中,我们对Boosting家族的Adaboost算法做了总结,本文就对Boosting家族中另一个重要的算法梯度提升树(Gradient Boosting De ...

随机推荐

  1. qt QMetaObject::connectSlotsByName()自动关联失效问题解决

    自己编写qt程序的时候,想使用qt on_objectName_signalName()命名规则自动关联信号和槽,老是发现失效.多方求解,答案事实上很简单就是没有理解objectName的含义. on ...

  2. 自动机理论、语言和计算导论 by John E. Hopcroft

    计算理论是计算机应用的基础,理论和应用缺一而不可. ---- 目录 ---- C01 自动机 C02 有穷自动机 C03 正则表达式与正则语言 C04 正则语言的性质 C05 上下文无关文法及上下文无 ...

  3. Java-->xml的pull解析

    --> pull解析器是android内置的解析器,解析原理与sax类似 --> xml文件student.xml: <?xml version="1.0" en ...

  4. xml json protobuf

    本文为原创,转载请注明:http://www.cnblogs.com/gistao/ Background xml,json,protobuf都是格式化手段,喜欢哪个,会用哪个,该用哪个,用哪个? 随 ...

  5. sql CONCAT字符串连接函数

    有的时候,我们有需要将由不同栏位获得的资料串连在一起.每一种资料库都有提供方法来达到这个目的: MySQL: CONCAT() Oracle: CONCAT(), || SQL Server: + C ...

  6. popwindow设置背景半透明

    WindowManager.LayoutParams lp = getWindow().getAttributes(); lp.alpha = 0.5f; //0.0-1.0 getWindow(). ...

  7. rsync异机备份

    参考http://www.cnblogs.com/itech/archive/2009/08/10/1542945.html 1.服务器 新建/etc/rsyncd.conf  ->新建/etc ...

  8. kuangbin_SegTree B (HDU 1754)

    跟A题类似 只是把update从增减直接改为赋值 query从求和改为求最大值 其他几乎一样 #include <cstdio> #include <cstring> #inc ...

  9. 综合使用union和limit区分结果并限制返回结果集的条数

    limit , 这里的limit限制了返回的union(合并)后的结果集,

  10. selenium多个窗口切换

    浏览器里面支持多窗口打开,例如这样: html里面写了: target="_blank" 造成新打开一个窗口,但是selenium不会自动跳转到新的串口,需要自己切换: # 你打开 ...