ML-Boosting 集成算法

来自: https://www.biaodianfu.com/boosting.html

简介

Boosting 即集成学习.

其核心思想是训练若干个弱学习器,并通过一定的结合策略,从而形成一个强学习器. 有时候也被称之为多分类器系统(multi-classifier system), 基于委员会的学习(committee-based learning)

分类

同质

同种类型的个体学习器集成,如决策树集成.

此类算法被称为基学习器算法 base learning algorithm

异质

不同类型的个体学习器集成,

此类算法被称为组件学习器 component algorithm

代表算法

如何从弱分类器变为强分类器?

大多数的集成方法都是通过改变训练数据的概率分布(或者说训练数据的权值分布),来针对不同训练分布调用弱学习算法学习一系列弱分类器.

这个过程中,有两个问题需要解决:

  1. 在每一轮如何改变训练数据的权值或概率分布

  2. 如何将弱分类器组合成一个强分类器

AdaBoost

针对第一个问题,提高那些被前一轮弱分类器错误分类样本的权值,并降低那些被正确分类的样本的权值.经过一轮的权值加大后,后一轮的弱分类器就会更关注那些没有被正确分类的样本. 持续下去,分类问题便会被一系列弱分类器“分而治之”。

针对第二个问题,即弱分类器的组合,AdaBoost采取加权多数表决法,具体的所,就是加大误差率小的弱分类器的权值,使其在表决中起更大的作用,另一方面,减小分类误差率大的弱分类器的权值,使其在表决中起较小的作用.

  • Box 1: 你可以看到我们假设所有的数据点有相同的权重(正号、负号的大小都一样),并用一个决策树桩D1将它们分为两部分。我们可以看到这个决策树桩将其中的三个正号标记的数据点分类错误,因此我们将这三个点赋予更大的权重交由下一个预测树桩进行分类。
  • Box 2: 在这里你可以看到三个未被正确分类的(+)号的点的权重变大。在这种情况下,第二个决策树桩D2试图将这三个错误的点准确的分类,但是这又引起新的分类错误,将三个(-)号标记的点识别错误,因此在下一次分类中,这三个(-)号标记的点被赋予更大的权重。
  • Box 3: 在这里三个被错误分类的(-)号标记的点被赋予更大的权重,利用决策树桩D3进行新的分类,这时候又产生了新的分类错误,图中用小圆圈圈起来的一个负号点和两个正号点
  • Box 4: 在这里,我们将D1、D2和D3三个决策器组合起来形成一个复杂的规则,你可以看到这个组合后的决策器比它们任何一个弱分类器表现的都足够好。

该原理可同样用于回归算法。它在不同权重的训练数据集上生成一系列的弱学习器,最开始的时候所有的数据拥有相同的权重,对于第一个分类器没有正确分类的点则在下一个决策器中的权重将会加大,作为一个迭代的过程,直到分类器数量达到预定值或预测精度达到预定值。大多数情况下,我们在AdaBoost中使用decision stamps。但是如果它可以接受带有权重的训练集,我们也可以使用其他任何的机器学习算法作为基础学习器。我们可以使用AdaBoost算法解决分类和回归问题。

from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import AdaBoostRegressor
from sklearn.tree import DecisionTreeClassifier
import matplotlib.pyplot as plt
import seaborn as sns 
import pandas as pd 
import numpy as np 
from sklearn.model_selection import train_test_split
from sklearn.metrics import accuracy_score

x1 = np.arange(0,100,1)
a = 0.3*x1 + 1
b = 0.3*x1 - 1
x2 = np.concatenate((a[0:50], b[50:]),axis=0)


data = []
idx = 0
for a_t,b_t in zip(x1.tolist(),x2.tolist()):
    if idx <50:
        data.append((a_t,b_t,0))
    else:
        data.append((a_t,b_t,1))
    idx += 1
data = pd.DataFrame(data,columns=['x1','x2','label'])


sns.scatterplot(data['x1'],data['x2'],hue=data['label'])
plt.show()


x_train = data[['x1','x2']].values
y_train = data['label'].values.astype('int')

x_train,x_test,y_train,y_test = train_test_split(x_train,y_train,test_size=0.3)

dt = DecisionTreeClassifier()
clf = AdaBoostClassifier(n_estimators=30,base_estimator=dt,learning_rate=1)

# Above I have used decision tree as a base estimator, you can use any ML learner as base estimator if it accepts sample weight

clf.fit(x_train,y_train.astype('int'))

accuracy_score(clf.predict(x_test),y_test)
/home/garden/anaconda3/envs/tf2/lib/python3.7/site-packages/seaborn/_decorators.py:43: FutureWarning: Pass the following variables as keyword args: x, y. From version 0.12, the only valid positional argument will be `data`, and passing other arguments without an explicit keyword will result in an error or misinterpretation.
  FutureWarning

png

0.9666666666666667

可以调整参数以优化算法的性能:

  • n_estimators:它控制了弱学习器的数量
  • learning_rate:控制在最后的组合中每个弱分类器的权重,需要在learning_rate和n_estimators间有个权衡
  • base_estimators:它用来指定不同的ML算法。

也可以调整基础学习器的参数以优化它自身的性能。

GBM Gradient Boosting Machine

  • 核心思想

每一次建立模型是在之间建立模型损失函数的梯度下降方向.

基于boosting框架的整体模型可以用线性组成式来描述,其中 h i ( x ) h_i(x) hi(x)为基模型与其权重的乘积:

F ( x ) = ∑ i m h i ( x ) F(x) = \sum_{i}^{m}h_i(x) F(x)=imhi(x)

模型的整体训练目标是使预测值 F ( x ) F(x) F(x)逼近真实值y,也就是说要让每一个基模型的预测值逼近各自要预测的部分真实值.由于同时要考虑所有基模型,导致整体模型训练变成了一个非常复杂的问题.

研究者们想到了一个贪心的解决手段:每次只训练一个基模型.则:

F i − 1 ( x ) + h i ( x ) F^{i-1}(x) + h_i(x) Fi1(x)+hi(x)

这样每一轮迭代中,只要集中解决一个基模型的训练问题: 使得 F i ( x ) F^i(x) Fi(x)逼近真实值y

与AdaBoost的区别

  • Gradient Boosting通过残差来变量的改变错误分类的权重,而AdaBoost就真的直接去修改分类错误的训练权重了
  • Gradient Boosting接入的分类器一般完整的决策树居多,但是AdaBoost一般使用二层决策树

Gradient Boosting中最有代表性的就是GBDT,该模型虽好,使用时理解数据以及正确调参才是王道

from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import accuracy_score


clf = GradientBoostingClassifier(n_estimators=100,learning_rate=1.0,max_depth=1)
clf.fit(x_train,y_train)

accuracy_score(clf.predict(x_test),y_test)
0.9666666666666667
  • n_estimators :控制弱学习器的数量
  • learning_rate:控制最后组合中弱学习器的权重,,需要在learning_rate和n_estimators间有个权衡
  • max_depth:单个回归估计的最大深度。最大深度限制了树的结点数量。调整该参数的最佳性能:最好的值取决于输入的变量

你可以调整损失函数以获得更好地性能。

XGBoost

  • 全称: Extreme Gradient Boosting 是GBDT的一种高效实现.

  • 基学习器: CART(gbtree)或者线性分类器(gblinear)

GBDT是一种使用gradient作为信息,将不同的弱分类decision trees进行加权,从而获得较好性能的方法。

GBDT的一般步骤

GBDT的一般步骤

Step 1: 初始化。初始化y_hat在第0时刻的值。
Step 2:求残差。通过类似梯度下降法的思路,每次y都向梯度下降的方向挪一小步。只是在GBDT,y挪的一小步并不是一个variable,而是一个function。
Step 3:构建决策树。使用决策树逼近这个残差 –g,得到第t个决策树:f_t。
Step 4:求叶节点权重。
Step 5:更新输出y。y(t) = y(t – 1) + learning_rate * f_t

XGBoost的变化

  • 变化1:提高了精度 – 对Loss的近似从一阶到二阶。。传统GBDT只使用了一阶导数对loss进行近似,而XGBoost对Loss进行泰勒展开,取一阶导数和二阶导数。同时,XGBoost的Loss考虑了正则化项,包含了对复杂模型的惩罚,比如叶节点的个数、树的深度等等。通过对Loss的推导,得到了构建树时不同树的score。具体score计算方法见论文Sec 2.2。
  • 变化2:提高了效率 – 近似算法加快树的构建。XGBoost支持几种构建树的方法。
    第一:使用贪心算法,分层添加decision tree的叶节点。对每个叶节点,对每个feature的所有instance值进行排序,得到所有可能的split。选择score最大的split,作为当前节点。
    第二:使用quantile对每个feature的所有instance值进行分bin,将数据离散化。
    第三:使用histogram对每个feature的所有instance值进行分bin,将数据离散化。
  • 变化3:提高了效率 – 并行化与cache access。XGBoost在系统上设计了一些方便并行计算的数据存储方法,同时也对cache access进行了优化。这些设计使XGBoost的运算表现在传统GBDT系统上得到了很大提升。

XGBoost与GBDT的区别

  • 传统GBDT以CART作为基分类器,xgboost还支持线性分类器,这个时候xgboost相当于带L1和L2正则化项的逻辑斯蒂回归(分类问题)或者线性回归(回归问题)。

  • 传统GBDT在优化时只用到一阶导数信息,xgboost则对代价函数进行了二阶泰勒展开,同时用到了一阶和二阶导数。顺便提一下,xgboost工具支持自定义代价函数,只要函数可一阶和二阶求导。

  • Xgboost在代价函数里加入了正则项,用于控制模型的复杂度。正则项里包含了树的叶子节点个数、每个叶子节点上输出的score的L2模的平方和。从Bias-variance tradeoff角度来讲,正则项降低了模型的variance,使学习出来的模型更加简单,防止过拟合,这也是xgboost优于传统GBDT的一个特性。

  • Shrinkage(缩减),相当于学习速率(xgboost中的eta)。xgboost在进行完一次迭代后,会将叶子节点的权重乘上该系数,主要是为了削弱每棵树的影响,让后面有更大的学习空间。实际应用中,一般把eta设置得小一点,然后迭代次数设置得大一点。(补充:传统GBDT的实现也有学习速率)

  • 列抽样(column subsampling)。xgboost借鉴了随机森林的做法,支持列抽样,不仅能降低过拟合,还能减少计算,这也是xgboost异于传统gbdt的一个特性。

  • 缺失值的处理。对于特征的值有缺失的样本,xgboost可以自动学习出它的分裂方向。

  • xgboost工具支持并行。boosting不是一种串行的结构吗?怎么并行的?注意xgboost的并行不是tree粒度的并行,xgboost也是一次迭代完才能进行下一次迭代的(第t次迭代的代价函数里包含了前面t-1次迭代的预测值)。xgboost的并行是在特征粒度上的。我们知道,决策树的学习最耗时的一个步骤就是对特征的值进行排序(因为要确定最佳分割点),xgboost在训练之前,预先对数据进行了排序,然后保存为block结构,后面的迭代中重复地使用这个结构,大大减小计算量。这个block结构也使得并行成为了可能,在进行节点的分裂时,需要计算每个特征的增益,最终选增益最大的那个特征去做分裂,那么各个特征的增益计算就可以开多线程进行。

  • 可并行的近似直方图算法。树节点在进行分裂时,我们需要计算每个特征的每个分割点对应的增益,即用贪心法枚举所有可能的分割点。当数据无法一次载入内存或者在分布式情况下,贪心算法效率就会变得很低,所以xgboost还提出了一种可并行的近似直方图算法,用于高效地生成候选的分割点。

XGBoost的优势

  • 显式地将树模型的复杂度作为正则项加在优化目标
  • 公式推导里用到了二阶导数信息,而普通的GBDT只用到一阶
  • 允许使用列抽样(column(feature)sampling)来防止过拟合,借鉴了Random Forest的思想,sklearn里的gbm好像也有类似实现。
  • 实现了一种分裂节点寻找的近似算法,用于加速和减小内存消耗。
  • 节点分裂算法能自动利用特征的稀疏性。
  • 样本数据事先排好序并以block的形式存储,利于并行计算
  • penalty function Omega主要是对树的叶子数和叶子分数做惩罚,这点确保了树的简单性。
  • 支持分布式计算可以运行在MPI,YARN上,得益于底层支持容错的分布式通信框架rabit。

实现

import numpy as np 
import pandas as pd 
import xgboost as xgb 
import matplotlib.pyplot as plt 

plt.style.use("ggplot")

%matplotlib inline

import xgboost as xgb 
import os 

dtrain = xgb.DMatrix(x_train,label=y_train)
dtest = xgb.DMatrix(x_test,label=y_test)

param = {'max_depth':2, 'eta':1, 'objective':'binary:logistic' }    # 设置XGB的参数,使用字典形式传入
num_round = 2     # 使用线程数
bst = xgb.train(param, dtrain, num_round)   # 训练
preds = bst.predict(dtest)   # 预测
preds = np.array([1 if e>0.5 else 0 for e in preds])
accuracy_score(preds,y_test)
[22:22:49] WARNING: /tmp/build/80754af9/xgboost-split_1619724447847/work/src/learner.cc:1061: Starting in XGBoost 1.3.0, the default evaluation metric used with the objective 'binary:logistic' was changed from 'error' to 'logloss'. Explicitly set eval_metric if you'd like to restore the old behavior.





1.0

总结

一般来说,Gradient Boosting(GB)方法适用于异质化数据。即,若你的数据集全由图片数据构成或者全由视频数据构成之类的,我们称其为同质化数据,这时使用神经网络往往会有更好的表现。但对于异质化数据,比如说数据集中有user gender,user age,也有content data等等的情况,GB方法的表现往往更好。GB方法比神经网络的入门门槛更低,使用起来也更简单。

NN和GB方法可以结合起来使用,并常常有很好的表现。我们可以使用NN方法学习embedding feature,并且和其他一些特征结合起来,再过GBDT。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值