前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >机器学习入门:硬核拆解GBDT

机器学习入门:硬核拆解GBDT

作者头像
统计学家
发布2020-07-02 15:14:03
1.1K0
发布2020-07-02 15:14:03
举报
文章被收录于专栏:机器学习与统计学

本文旨用小例子+可视化的方式拆解GBDT原理中的每个步骤,使大家可以彻底理解GBDT

Boosting到Gradient Boosting

Boosting是集成学习的一种基分类器(弱分类器)生成方式,核心思想是通过迭代生成了一系列的学习器,给误差率低的学习器高权重,给误差率高的学习器低权重,结合弱学习器和对应的权重,生成强学习器。

前文讲过的AdaBoost就是典型的Boosting算法

Boosting算法要涉及到两个部分,加法模型和前向分步算法。

加法模型就是说强分类器由一系列弱分类器线性相加而成。一般组合形式如下:

其中,就是一个个的弱分类器,是弱分类器学习到的最优参数,β就是弱学习在强分类器中所占比重,P是所有α和β的组合。这些弱分类器线性相加组成强分类器。

前向分步就是说在训练过程中,下一轮迭代产生的分类器是在上一轮的基础上训练得来的。也就是可以写成这样的形式:

Gradient Boosting

Boosting 算法(以AdaBoost为代表)用错分数据点来识别问题,通过调整错分数据点的权重来改进模型。Gradient Boosting通过负梯度来识别问题,通过计算负梯度来改进模型。

Gradient Boosting每次迭代的目标是为了减少上一次的残差,在残差减少的梯度(Gradient)方向上建立一个新的模型,每个新的模型的建立是使之前模型的残差往梯度方向减少。

第t轮的第i个样本的损失函数的负梯度为:

此时不同的损失函数将会得到不同的负梯度,如果选择平方损失

负梯度为

此时我们发现GBDT的负梯度就是残差,所以说对于回归问题,我们要拟合的就是残差。

GBDT回归算法原理

输入是训练集样本, 最大迭代次数T, 损失函数L。输出是强学习器

  1. 初始化弱学习器
  2. 对迭代轮数t=1,2,...T有:

a)对样本,,计算负梯度

b)利用, 拟合一颗CART回归树,得到第t颗回归树,其对应的叶子节点区域为。其中J为回归树t的叶子节点的个数。

c) 对叶子区域,计算最佳拟合值

d)更新强学习器

  1. 得到强学习器f(x)的表达式

GBDT分类算法

对于二元GBDT,如果用类似于逻辑回归的对数似然损失函数,则损失函数为:其中y∈{1,+1}。则此时的负梯度误差为

对于生成的决策树,我们各个叶子节点的最佳负梯度拟合值为

由于上式比较难优化,我们一般使用近似值代替

除了负梯度计算和叶子节点的最佳负梯度拟合的线性搜索,二元GBDT分类和GBDT回归算法过程相同。

小例子+可视化理解GBDT

上面对原理进行了分析之后,大致对GBDT有了一定的认识,为了更加形象的解释GBDT的内部执行过程,这里引用《统计学习方法》中adaboost一节中的案例数据来进行进一步分析。强烈建议大家对比学习,看一下Adaboost和 GBDT 的区别和联系。数据集如下:

采用GBDT进行训练,为了方便,我们采用MSE作为损失函数,并且将树的深度设为1,决策树个数设为5,其他参数使用默认值

代码语言:javascript
复制
import numpy as np
import pandas as pd
from sklearn import tree
import matplotlib.pyplot as plt
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.model_selection import train_test_split 

X = np.arange(1,11)
y = np.array([5.56, 5.70, 5.91, 6.40, 6.80, 7.05, 8.90, 8.70, 9.00, 9.05])

gbdt = GradientBoostingRegressor(n_estimators=5,max_depth=1)
gbdt.fit(X.reshape(-1,1),y)

其中GradientBoostingRegressor主要参数如下

代码语言:javascript
复制
GradientBoostingRegressor(alpha=0.9, criterion='friedman_mse', init=None,
learning_rate=0.1, loss='ls', max_depth=1,
max_features=None, max_leaf_nodes=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=5,
n_iter_no_change=None, presort='auto',
random_state=None, subsample=1.0, tol=0.0001,
validation_fraction=0.1, verbose=0, warm_start=False)

其他参数为决策树参数,大家应该已经很熟悉了,不再赘述。

下面我们根据GBDT回归算法原理,开始分步拆解:

「第一步」:根据初始化公式 可以计算出(本例中,恰好为yi均值)

「第二步」:计算损失函数的负梯度值:

由于是MSE损失,上式等于,结果如下:

代码语言:javascript
复制
#计算残差
y - y.mean()
[out]:
array([-1.747, -1.607, -1.397, -0.907, -0.507, -0.257,  1.593,  1.393,
        1.693,  1.743])

第三步:对上面残差拟合第一棵树 根据所给的数据,可以考虑的切分点为1.5、2.5、3.5、4.5、5.5、6.5、7.5、8.5、9.5分别计算的值,并计算出切分后的左右两侧加和MSE最小的切分,最后得到的是6.5

找到最佳的切分点之后,我们可以得到各个叶子节点区域,并计算出和.此时,为小于6.5的数据,为x大于6.5的数据。

print((y - y.mean())[:6].mean(),(y - y.mean())[6:10].mean())[out]:-1.07 1.605 #计算mse print( ((y - y.mean())**2).mean(), ((y[:6] - y[:6].mean())**2).mean(), ((y[6:10] - y[6:10].mean())**2).mean())[out] 1.911421 0.309689 0.0179686

第一棵树的可视化

代码语言:javascript
复制
tree.plot_tree(gbdt[0,0],filled=True)

「最后」:更新的值 ,其中为学习率,或称shrinkage,目的是防止预测结果发生过拟合,默认值是0.1。

「至此第一轮迭代完成」,后面的迭代方式与上面一样, 本例中我们生成了5棵树,大家可以用「tree.plot_tree」可视化其他树

迭代次后,第次的即为最终的预测结果。

「课后作业」,大家可以思考一下,第二棵树中的value是如何计算出来的?其实很简单哈??

参考

https://www.cnblogs.com/pinard/p/6140514.html https://blog.csdn.net/u014168855/article/details/105481881 https://www.csuldw.com/2019/07/12/2019-07-12-an-introduction-to-gbdt/

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-07-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 机器学习与统计学 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Boosting到Gradient Boosting
    • Gradient Boosting
      • GBDT回归算法原理
        • GBDT分类算法
        • 小例子+可视化理解GBDT
        • 参考
        领券
        问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档