GBDT的决策树:

​ 无论是处理回归任务还是二分类以及多分类任务,GBDT使用的决策树是CART回归树。因为GBDT每次迭代要拟合的是梯度值,是连续值所以要用回归树。

​ 对于回归树算法来说最重要的是寻找最佳的划分点,那么回归树中的可划分点包含了所有特征的所有可取的值。在分类树中最佳划分点的判别标准是熵或者基尼系数,都是用纯度来衡量的,但是在回归树中的样本标签是连续数值,所以再使用熵之类的指标不再合适,取而代之的是平方误差,它能很好的评判拟合程度。

注意:

  • 梯度下降从来都是拟合负梯度,GBDT平方损失只是恰好等于残差

  • 训练步骤:

    • 每棵决策树利用负梯度对样本点进行划分(拟合负梯度)
    • 求使得损失函数最小的C(即树叶子结点的输出),且C的值通常是一个与负梯度相关的式子(见下文分类问题模块介绍)

提升树(Boosting Tree)

​ 先来个通俗理解:假如有个人30岁,我们首先用20岁去拟合,发现损失有10岁,这时我们用6岁去拟合剩下的损失,发现差距还有4岁,第三轮我们用3岁拟合剩下的差距,差距就只有一岁了。如果我们的迭代轮数还没有完,可以继续迭代下面,每一轮迭代,拟合的岁数误差都会减小。最后将每次拟合的岁数加起来便是模型输出的结果。

Gradient Boosting:拟合负梯度

​ 当损失函数是平方损失和指数损失函数时,提升树(Boosting Tree)每一步优化是很简单的,但是对于一般损失函数而言,往往每一步优化起来不那么容易,针对这一问题,Freidman提出了梯度提升树算法,这是利用最速下降的近似方法,其关键是利用损失函数的负梯度作为提升树算法中的残差的近似值。

​ Gradient Boosting 的基本思想是:串行地生成多个弱学习器,每个弱学习器的目标是拟合先前累加模型的损失函数的负梯度, 使加上该弱学习器后的累积模型损失往负梯度的方向减少。即如果第 m 轮弱学习器拟合损失函数关于累积模型 的负梯度,则加上该弱学习器之后累积模型的 loss 会最小。(个人理解是:随着m棵树的不断叠加使得模型的整体梯度趋近于0,模型近似最优

GBDT算法原理

GBDT 回归与分类

  • GBDT(Gradient Boosting Decision Tree)是弱学习器使用 CART 回归树的一种 Gradient Boosting,使用决策树作为弱学习器的一个好处是:决策树本身是一种不稳定的学习器(训练数据的一点波动可能给结果带来较大的影响),从统计学的角度单棵决策树的方差比较大。而在集成学习中,弱学习器间方差越大,弱学习器本身泛化性能越好,则集成学习模型的泛化性能就越好。因此使用决策树作为弱学习器通常比使用较稳定的弱学习器(如线性回归等)泛化性能更好。

  • 回归问题

    GBDT 中的每个弱学习器都是 CART 回归树,在回归问题中,损失函数采用均方损失函数:



    损失函数的负梯度为:



    核心代码如下:

    def fit(self, train_X, train_y):
    self.estimator_list = list()
    self.F = np.zeros_like(train_y, dtype=float) for i in range(1, self.n_estimators + 1):
    # get negative gradients
    neg_grads = train_y - self.F
    base = DecisionTreeRegressor(max_depth=self.max_depth)
    base.fit(train_X, neg_grads) # cart树的叶结点值是负梯度,也是残差
    train_preds = base.predict(train_X)
    self.estimator_list.append(base) if self.is_first:
    self.F = train_preds
    self.is_first = False
    else:
    self.F += self.lr * train_preds
  • 分类问题

    GBDT 中都的弱学习器都是 CART 回归树,在回归问题上使用 GBDT 比较 intuitive,损失函数为均方损失,负梯度就是残差,下一棵树就去拟合之前的树的和与真实值的残差。对于分类问题,可以对拟合目标稍作转换实现分类。

    基本的思路可以参考线性回归通过对数几率转化为逻辑回归进行分类。逻辑回归也是广义上的线性模型,可以看做是线性回归模型去拟合对数几率







    可以看到最后的负梯度形式十分简洁,将此负梯度作为第 m 轮的拟合目标,依次不断迭代,GBDT 分类的核心代码如下:

    @staticmethod
    def logit(F):
    return 1.0 / (1.0 + np.exp(-F)) def fit(self, train_X, train_y):
    self.estimator_list = list()
    self.F = np.zeros_like(train_y, dtype=float) for i in range(1, self.n_estimators + 1):
    # get negative gradients
    neg_grads = train_y - self.logit(self.F)
    base = DecisionTreeRegressor(max_depth=self.max_depth)
    base.fit(train_X, neg_grads) #cart树的叶结点值是负梯度,不是实际标签的残差(个人理解,若有错误,请不吝指教)
    train_preds = base.predict(train_X) # train_preds 即为C
    self.estimator_list.append(base) if self.is_first:
    self.F = train_preds
    self.is_first = False
    else:
    self.F += self.lr * train_preds
    ```

GBDT 优点和局限性

  • 优点
  1. 预测阶段速度快,树与树之间可以并行预测
  2. 在数据分布稠密的数据上,泛化能力和表征能力都很好
  3. 使用 CART 作为弱分类器不需要对数据进行特殊的预处理如归一化等
  • 局限性
  1. 在高维稀疏的数据上,表现不如 SVM 或神经网络
  2. 训练过程需要串行训练,只能在决策树内部采用一些局部并行手段提高训练速度

参考链接:

小点

  • 同一棵树中可以多次利用同一特征进行划分

  • GBDT中会出现两棵树(除叶子结点外)结构相同的情况吗?
    • 学习率太小(把一棵树一次可以拟合好的树,让这棵树分多次来拟合)?

GBDT初识的更多相关文章

  1. Android动画效果之初识Property Animation(属性动画)

    前言: 前面两篇介绍了Android的Tween Animation(补间动画) Android动画效果之Tween Animation(补间动画).Frame Animation(逐帧动画)Andr ...

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

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

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

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

  4. 初识Hadoop

    第一部分:              初识Hadoop 一.             谁说大象不能跳舞 业务数据越来越多,用关系型数据库来存储和处理数据越来越感觉吃力,一个查询或者一个导出,要执行很长 ...

  5. python学习笔记(基础四:模块初识、pyc和PyCodeObject是什么)

    一.模块初识(一) 模块,也叫库.库有标准库第三方库. 注意事项:文件名不能和导入的模块名相同 1. sys模块 import sys print(sys.path) #打印环境变量 print(sy ...

  6. 初识IOS,Label控件的应用。

    初识IOS,Label控件的应用. // // ViewController.m // Gua.test // // Created by 郭美男 on 16/5/31. // Copyright © ...

  7. UI篇(初识君面)

    我们的APP要想吸引用户,就要把UI(脸蛋)搞漂亮一点.毕竟好的外貌是增进人际关系的第一步,我们程序员看到一个APP时,第一眼就是看这个软件的功能,不去关心界面是否漂亮,看到好的程序会说"我 ...

  8. Python导出Excel为Lua/Json/Xml实例教程(一):初识Python

    Python导出Excel为Lua/Json/Xml实例教程(一):初识Python 相关链接: Python导出Excel为Lua/Json/Xml实例教程(一):初识Python Python导出 ...

  9. 初识SpringMvc

    初识SpringMvc springMvc简介:SpringMVC也叫Spring Web mvc,属于表现层的框架.Spring MVC是Spring框架的一部分,是在Spring3.0后发布的 s ...

  10. 初识redis数据类型

    初识redis数据类型 1.String(字符串) string是redis最基本的类型,一个key对应一个value. string类型是二进制安全的.意思是redis的string可以包含任何数据 ...

随机推荐

  1. [C#]C++/CLI中interior_ptr和pin_ptr的区别

    interior_ptr 当垃圾回收器移动对象时,Interior pointer能随之移动,并始终指向该对象. 但是如果把这个指针返回给外部函数,那么当垃圾回收时(垃圾回收期间会压缩对象,),对象地 ...

  2. 【Redis实战专题】「性能监控系列」全方位探索Redis的性能监控以及优化指南

    Redis基本简介 Redis是一个开源(BSD 许可).内存存储的数据结构服务器,可用作数据库,高速缓存和消息队列代理.它支持字符串.哈希表.列表.集合.有序集合等数据类型.内置复制.Lua 脚本. ...

  3. AIR32F103(八) 集成Helix MP3解码库播放MP3

    目录 AIR32F103(一) 合宙AIR32F103CBT6开发板上手报告 AIR32F103(二) Linux环境和LibOpenCM3项目模板 AIR32F103(三) Linux环境基于标准外 ...

  4. 轻松理解Promise.all 、Promise.then、Promise.race有什么区别以及使用方法

    简单来说呢,Promse.all一般应用于某个场景需要多个接口数据合并起来才能实现 有个极大地好处我必须说一下,请求顺序和获取数据顺序是一样的哟,大可放心使用~~ const success1 = n ...

  5. Java 进阶P-8.15

    对象串行化 ObjectInputStream类 readObject() ObjectOutputStream类 writeObject() Serializable接口 对象的寿命通常随着生成该对 ...

  6. 用if语句替换三元运算符-标准的switch语句

    用if语句替换三元运算符 在某些简单的应用中,if语句是可以和三元运算符互换使用的. public static void main(String[] args) { int a = 10; int ...

  7. CSS 3 所有的选择器整理(2023.2)

    你知道的和你不知道的所有选择器.不包含尚未广泛实现的,也不包含已弃用的. 基本的选择器规则(Selector) 类型(Type)选择器 直接用标签匹配特定的元素 span { ... } p { .. ...

  8. Nacos配置中心 (介绍与配置)

    Nacos配置中心 当微服务部署的实例越来越多,达到数十.数百时,逐个修改微服务配置就会让人抓狂,而且很容易出错.我们需要一种统一配置管理方案,可以集中管理所有实例的配置. Nacos一方面可以将配置 ...

  9. 视觉SLAM:VIO的误差和误差雅可比矩阵

    1.两个相机之间的非线性优化 观测相机方程关于相机位姿与特征点的雅可比矩阵: 1.1 位姿: 1.2 3D特征点 fx,fy,fz为相机内参 X',Y',Z'为3D点在相机坐标系下的坐标 该误差是观测 ...

  10. 如何将项目打包成apk或exe程序

    一. 打包成exe 确认已经安装了pyinstaller,然后依次执行下面指令 pyinstaller -F setup.py 打包exe pyinstaller -F -w setup.py 不带控 ...