29

一文理清集成学习知识点(Boosting&Bagging)

 4 years ago
source link: http://mp.weixin.qq.com/s?__biz=MzUxNDMzMjgxNQ%3D%3D&%3Bmid=2247490562&%3Bidx=1&%3Bsn=e8228a4dc689beafc8b146f5ddcca332
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

导读

相信这个环节的内容大家都会比较熟悉的,因为我们经常用到的XGBoost、GBDT就是集成模型,今天这里就给大家系统地梳理一下知识点和原理,做到了然于胸。

目录

  • 集成学习的主要类型

  • 集成学习的基本步骤

  • 谈谈基分类器

  • GBDT与XGBoost的区别与联系

  • 算法实践Demo

集成学习的主要类型

集成学习是一大类模型融合策略和方法的统称,我们经常用到的两类是Boosting和Bagging,这两者的区别与联系经常会被问到,在回答这些问题前,需要对两者的原理进行统一了解。

Boosting

Boosting方法在训练基分类器时采用的是串行的方法,每一个基分类器依赖前面的结果。它的基本思路就是将基分类器层层叠加,每层在训练时都会对前一层基分类器的分类错误情况去改变当前样本的分布,具体来说就是将分类错误的样本给予更高的权重,所以每一次的迭代,数据分布都是不一样的。

Boosting的迭代过程与人类的学习过程有点类似,也就是说我们在学习新知识的时候,会记住部分信息,也会遗忘部分信息,所以在下一次中会着重去关注没记住的内容,加强训练,这样子不断地去循环学习,直到我们能够全部吸收。

Boosting通过逐步聚焦于基分类器分错的样本,减少集成分类器的偏差。

Bagging

而对于Bagging,它则是并行训练的,各个基分类器之间无依赖,而且每个基分类器训练的样本都是一样的(也可以不同),但由于每个基分类器的"学习能力"不同,会出现很多的学习结果,最终的决策会参考这些基分类器的结果,一般是采用投票的方式,基分类器之间的权重都是一样的。

Bagging采取分而治之的策略,通过对训练样本多次采样,并分别训练出多个不同模型,然后做综合,来减少集成分类器的方差。

集成学习的基本步骤

集成学习一般可以分为以下3个步骤:

1、找到误差互相独立的基分类器

2、训练基分类器

3、合并基分类器的结果

合并基分类器的方法有voting和stacking两种,前者是用投票的方法,将获得最多选票的结果作为最终的结果。后者则是使用串行的方法,把前一个基分类器的结果输出到下一个基分类器中,将所有基分类器的输出结果相加融合作为输出。

比如,针对Adaboost,大致的步骤如下:

(1) 确定基分类器:一般都是采用树形模型,因为它结构简单且随机性强。

(2) 训练基分类器:假设有T个基分类器,则可以按照如下过程来训练基分类器:

6reaiiU.png!web

(3) 合并基分类器:给定一个未知样本z,输出分诶结果为加权投票的结果。

从上面的例子中我们可以看出来Boosting一个很重要的思想,那就是它会对分类错误的样本进行权重的加强,对分类正确的样本降低权重,在最后的模型融合时根据错误率对基分类器进行加权融合,错误率低的分类器也拥有更大的"话语权"。

还有一种比较流行的Boosting模型,那就是 梯度提升决策树(GBDT) 。其核心思想就是每一棵树学的是之前所有树结论和的残差,这个残差是一个加预测值后能得到真实值的累加(减)量。

谈谈基分类器

基分类器作为Boosting的基本单元,而且一般也是会采用决策树来作为分类器,原因有三:

(1) 决策树可以较为方便地将样本的权重整合到训练过程中,而不需要使用过采样的方法来调整样本权重;

(2) 决策树的表达能力和泛化能力都是有很大的调节性,比如可以通过数的深度来调整;

(3) 决策树的随机性较强,所以不同的训练集都会比较随机地生成不同的决策树模型,这样子的"不稳定学习器"更能胜任基分类器的职责,很好的解决了数据样本扰动的影响,同时解决过拟合情况。

Q: 可否将RF中的决策树基分类器,替换为K-Mean或者线性分类器呢?

有了上面我们对于基分类器的认识,因为RF属于Bagging,它要求的基分类器最好是对样本分布较为敏感,这样子基分类器之间的方差就会较大,然后综合起来之后就可以达到一个较优的结果。而如果换成K-Mean或者线性分类器,这些分类器本身会非常稳定,这样子的话其实基分类器训练出来的模型都是十分相似,方差很小,即便Bagging之后不能获得更好的表现,失去了Bagging的优势。

GBDT与XGBoost的区别与联系

GBDT

Gradient Boosting Decision Tree,简称GBDT,中文名为梯度提升决策树,作为"网红"算法,时常出现在各大竞赛平台和商业应用,它的核心思想就是从错误中学习,基于决策树预测的残差进行迭代优化学习,具体做法就是根据当前模型损失函数的负梯度信息来训练新加入的弱分类器,然后将训练好的弱分类器以累加的形式结合到现有模型中。

XGBoost

作为一个比GBDT更加"网红"的机器学习算法,XGBoost可谓是鼎鼎大名,它高效地实现了GBDT算法并进行算法和工程层面上的优化改进,它直接并行训练模型(这里的并行指的是节点分裂上的并行,模型的训练还是串行的,毕竟还是属于Boosting),然后对过拟合做了一些优化措施,也优化了Cost Function。

区别与联系

这里就罗列一些内容:

(1) 在使用CART作为基分类器的时候,XGBoost显式地加入了正则项来控制模型的复杂度,有利于改善模型的过拟合情况,从而提高模型的泛化能力;

(2) GBDT在训练模型的时候只是使用Cost Function的一阶导数部分信息,而XGBoost则是进行二阶泰勒展开,用到了二阶导数;

(3) 传统的GBDT只是采用CART作为基分类器,而XGBoost支持多种基分类器,比如线性分类器;

(4) GBDT每次训练模型的样本都是一样的,但是XGBoost则支持对数据进行采用,数据分布有可能会发生改变;

(5) GBDT没有对缺失值进行处理,XGBoost对这块有针对性的解决措施。

算法实践Demo

先前的一篇文章中,有读者在咨询有没有调用这些算法的例子,这边的话就根据算法的官方文档,整理出一份demo,希望也可以帮助到正在初学的朋友。

XGBoost

我们在Python里用XGBoost,主要就是通过调用Scikit_learn的包,里面有一个类叫 xgboost。当我们对样本进行处理后,得到一个很规范的DataFrame格式的数据集,这个时候就可以调用这个算法类来进行模型构建,具体参数如下:

Scikit-Learn Wrapper interface for XGBoost.

  • class xgboost.XGBRegressor(max_depth=3, learning_rate=0.1, n_estimators=100, verbosity=1, objective='reg:squarederror', booster='gbtree', tree_method='auto', n_jobs=1, gamma=0, min_child_weight=1, max_delta_step=0, subsample=1, colsample_bytree=1, colsample_bylevel=1, colsample_bynode=1, reg_alpha=0, reg_lambda=1, scale_pos_weight=1, base_score=0.5, random_state=0, missing=None, num_parallel_tree=1, importance_type='gain', **kwargs)

下面是一个具体的实例,大家可以结合代码里的注释来理解这段代码:

# 导入相关库

import xgboost as xgb

from xgboost.sklearn import XGBClassifier


# 初始化xgb

xgb = XGBClassifier(learning_rate =0.1,eta=0.5, max_depth=3,min_child_weight=2,gamma=0.2, subsample=0.7, colsample_bytree=0.9,

objective= 'binary:logistic', scale_pos_weight=10, seed=10)


# 用样本数据训练模型

xgb.fit(X_train, y_train)


# 对训练好的模型进行预测应用,分别对训练集和测试集进行计算

train_y_pred = xgb.predict(X_train)

train_y_predprob = xgb.predict_proba(X_train)[:,1]

test_y_pred = xgb.predict(X_test)

test_y_predprob = xgb.predict_proba(X_test)[:,1]


# 计算KS值,并打印出来,看模型效果(这里除了KS值,还有很多其他的指标,具体根据实际情况选择)

get_ks = lambda y_pred,y_true: ks_2samp(y_pred[y_true==1], y_pred[y_true!=1]).statistic

print('训练KS值: %s' %get_ks(train_y_predprob,y_train))

print('验证KS值: %s' %get_ks(test_y_predprob,y_test))

References

[1] 百面机器学习 Chapter12 (文中未标识来源的图片均来自本书内容)

[2] XGBoost Documentation

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

封面图来源:Photo by Matthew Guay  on  Unsplash

6JVj63n.jpg!web


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK