集成学习(六)

本文详细介绍了集成学习算法中的AdaBoost、GBDT和XGBoost,探讨了它们之间的关系和区别。GBDT在不同损失函数下如何退化或转化为其他算法,以及它们的优化策略,如XGBoost的正则项和一步到位的优化。通过手动计算和sklearn库的实现,验证了理论分析的准确性。
摘要由CSDN通过智能技术生成

1.无论是分类问题还是回归问题,GBDT建立的决策树都是回归树

2.当损失函数是指数损失时,GBDT退化为AdaBoost分类算法

3.GBDT拟合最优解利用了泰勒展开二阶信息的近似解

4.GBDT以负梯度为目标先建树,再执行直线搜索求解最优值,而XGB一步到位

5.GBDT与XGBoost决策树的分裂标准评价指标不同

6.XGBoost加入了正则项,考虑树结构和树预测值的复杂度

本篇对集成学习算法AdaBoost、GBDT、XGBoost做一个总结和补充,并介绍sklearn实现细节。我们通过一个小样例手推结果并与sklearn比较,彻底对集成学习算法是如何实现有一个感性的理解。便于在以后工作中不仅仅只会调包实现,还能针对性发现问题

以及提出改进方案。

注:关于集成学习算法推导见集成学习(三)集成学习(四)集成学习(五)

算法总结

我们从均方误差为损失函数的GBDT回归算法出发来梳理三者的关系。

这里关键要理解(b)和(c)步,(b)是以整体损失函数对前K-1轮学习器F的导数的负梯度为拟合目标构建决策树,其分裂标准跟决策树一样,接下来对叶子节点的赋值与常规决策树赋值方式不同(常规决策树赋值标准是多数法或均值法),这里的赋值方式就是(c)步,执行一次直线搜索,找到使得全局损失函数最小的拟合值(并非当前第K轮弱学习器决策树损失最小的拟合值)。

通常来说,直接求解(c)步的最优解r是很复杂的,我们利用泰勒展开来求解近似值:

所以,第K轮弱学习器每个叶子节点的最优解r就是一元二次方程的驻点,它刚好等于-g/h(g是一阶导,h是二阶导),要是叶子节点有m个样本,就是m个样本一阶导之和除以二阶导之和。

因此,GBDT回归算法拟合的是残差,叶子节点最优解就是拟合目标均值,这个跟回归决策树叶子节点赋值方式一样。

对于不同的损失函数,得到的负梯度不同,进而最优解的表达式不同,仅此而已,我们给出分类问题不同损失函数拟合的目标值以及最优解

交叉熵损失和负对数似然损失都是逻辑回归的损失函数,它们是对目标y值不同的表达形式,它们是等价的。

我们可以看出,无论是分类问题还是回归问题,GBDT建立的决策树都是回归树,所谓

的分类回归,是针对目标y值不同建立不同的损失函数而对应。

同时,仔细观察指数损失的分类问题,就是跟AdaBoost分类问题等价的,因此,当损失函数是指数损失时,GBDT退化为AdaBoost分类算法,损失函数一致,因为中间变形的不同,GBDT针对目标y建模,AdaBoost侧重样本权重。

我们也可以看出,GBDT在拟合最优值时,利用了泰勒展开的二阶导信息,那么我们常说的XGBoost展开到二阶导又是怎么回事呢。

实际上,XGBoost是把GBDT的(b)、(c)步合起来一步完成,就是建立决策树和直线搜索最优解一次完成。同时,为了防止过拟合,还加入了正则项,最后其叶子节点最优解是:

如果正则系数为0,就跟GBDT直线搜索的结果完全相同。

由于是一步到位,所以决策树的分裂规则不再是常规决策树的分裂规则,它的分裂评价标准是:

寻找最佳分裂有Exact和Approx算法,更多细节见集成学习(五),这里不再赘述。

由此,我们可以总结:

  • 无论是分类问题还是回归问题,GBDT建立的决策树都是回归树

  • 当损失函数是指数损失时,GBDT退化为AdaBoost分类算法

  • GBDT拟合最优解利用了泰勒展开二阶信息的近似解

  • GBDT以负梯度为目标先建树,再执行直线搜索求解最优值,而XGB一步到位

  • GBDT与XGBoost决策树的分裂标准评价指标不同

  • XGBoost加入了正则项,考虑树结构和树预测值的复杂度

从手动到sklearn实现

三种算法的sklearn包如下:

from sklearn.ensemble import AdaBoostRegressor
from sklearn.ensemble import AdaBoostClassifier

from sklearn.ensemble import GradientBoostingRegressor
from sklearn.ensemble import GradientBoostingClassifier

from xgboost import XGBClassifier
from xgboost import XGBRegressor

下一节我们再介绍其参数,这节我们先感受其算法实现过程。

我们通过一个小样例手动计算一下这三个算法是怎么实现的,然后对比sklearn调包的结果是否一致,以此也可以验证小编的理解是否有偏差。我们先介绍样例:

X1和X2是两个维度,y是目标取值

假设分裂标准都是mse,为了方便演示,决策树深度限制为1,学习率设置为1,迭代3次,即建立3次弱学习器。

我们先来看GBDT回归算法,利用excel表手动计算三棵树的结果:

呈现一下每棵树的指标:

利用sklearn包GradientBoostingRegressor来看看结果是否一致。

model = GradientBoostingRegressor(
            loss='ls',criterion='mse',
            n_estimators=3,learning_rate = 1,
            max_depth=1,random_state=0)
model.fit(X,y) 

clf = model.estimators_[0][0]
dot_data = tree.export_graphviz(clf, 
            out_file=None,feature_names=f_name, 
           filled=True,rounded=True,
           special_characters=True,proportion=False,
            rotate=False,precision=2)

graph = pydotplus.graph_from_dot_data(dot_data)
Image(graph.create_png())


sklearn包跑的结果与手动计算的完全一致,可见,GBDT内置代码树建立与最优解实现过程与上一节分析过程吻合。

我们再来看分类问题的实现过程。

负对数似然损失:

交叉熵损失:

这两个损失是等价的。我们再来看看sklearn实现结果

model = GradientBoostingClassifier(
          loss='deviance',
          criterion='mse',
          n_estimators=3,
          learning_rate = 1,
          max_depth=1,
          random_state=0)

model.fit(X,y)

结果一致。

最后来看看指数损失:

同样看看sklearn的实现效果:

model = GradientBoostingClassifier(
           loss='exponential',
           criterion='mse',
           n_estimators=3,
           learning_rate = 1,
           max_depth=1,
           random_state=0)

model.fit(X,y)

结果一致。

上一节介绍过,当损失函数为指数损失时,GBDT退化为AdaBoost分类,我们在集成学习(三)已经手推了一个案例,数据也是本文的数据,只不过第二个和第三个弱学习器调换了,我们就换回来,跟本文的一样,直接给出手推的过程:

我们用sklearn来检验一下小编手推结果是否一致。

model = AdaBoostClassifier(n_estimators=3,random_state=0,algorithm='SAMME')
model.fit(X,y)

三次迭代的错误率和弱学习器的权重与excel手推结果一致。

但这里要注意,AdaBoostClassifier包的参数algorithm要设置为SAMME才是手推,但其还有另外一个实现更快的优化算法,就是参数设置为SAMME.R,此时弱学习器的权重均为1.这两者不同的地方是:前者用对样本集分类效果作为弱学习器权重,后者使用了对样本集分类的预测概率大小来作为弱学习器权重。但结果是一致的,这里不用过多纠结。

sklearn包参数

这节介绍集成算法sklearn包的参数。主要介绍最重要的参数,其他参数见官方文档说明

AdaBoostClassifier

  • base_estimator:初始学习器,默认是决策树

  • n_estimators:子学习器的数量

  • learning_rate:学习率,步长。加在弱学习器前面的参数

  • algorithm:就是上节提到的实现方式

AdaBoostRegressor比分类的多了一个参数loss,就是损失函数定义,详情见集成学习(三),具体有

线性误差:‘linear’

平方误差:‘square’,

指数误差:‘exponential’

GradientBoostingClassifier

  • loss:损失函数,‘deviance’(负对数似然损失),‘exponential’(指数损失)

  • init:初始学习器

  • n_estimators:弱学习器个数

  • learning_rate:学习率,步长。取值范围(0,1]

  • subsample:正则化项,子采样比例

  • ccp_alpha:决策树剪枝惩罚系数

  • criterion:决策树划分标准,'mse','mae','friedman_mse'

  • min_samples_split:决策树非叶子节点最小分裂样本数

  • min_samples_leaf:决策树叶子节点最小样本数

  • max_depth:决策树的最大深度

GradientBoostingRegressor大同小异,就是损失函数的定义有差别,再有采取huber损失或分位数损失时的参数alpha,其他无大差别,这里不再赘述。

XGBoost

  • booster:弱学习器类型,默认是gbtree

  • n_estimators:弱学习器的个数

  • objective:定义分类或回归以及损失函数,均方误差reg:squarederror ,二分类binary:logistic,多分类multi:softmax

  • learning_rate:学习率

  • subsample: 子采样参数,与GBDT一致

  • max_depth:树的最大深度

  • min_child_weight:最小的子节点权重阈值,如果某个树节点的权重小于这个阈值,则不会再分裂。原理是某个节点所有样本二阶导(h)之和

  • reg_alpha:决策树结构复杂度参数,就是叶子节点个数|T|对应的γ参数

  • reg_lambda:决策树预测值复杂度参数,就是λ值

  • gamma:决策树分裂所带来的损失减小(ΔL)阈值,也就是分裂标准要达到的最小阈值

更多内容见官方文档,链接在最后参考链接里。

XGBoost可视化

另外,我们还要介绍一下XGBoost可视化的问题。我们沿用本文的样例。代码如下

import xgboost as xgb
from xgboost import plot_tree
from xgboost import XGBClassifier
from xgboost import XGBRegressor

model = XGBRegressor(
             n_estimators=3,
             max_depth=1,
             learning_rate=1,
             reg_alpha=0,
             reg_lambda=0, 
             objective='reg:squarederror',
             random_state=0)

model.fit(X,y)

xgb.to_graphviz(
       model,num_trees=0,yes_color='#32CD32',no_color='#DAA520',
    leaf_node_params={'shape': 'box',
       'style': 'filled',
       'fillcolor': '#e48038'}
)

参考资料:

https://scikit-learn.org/stable/user_guide.html

https://www.cnblogs.com/pinard/p/6143927.html

https://www.cnblogs.com/pinard/p/6136914.html

https://www.cnblogs.com/pinard/p/11114748.html

https://xgboost.readthedocs.io/en/latest/parameter.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

整得咔咔响

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值