赞
踩
* * * The Machine Learning Noting Series * * *
一 简介
二 AdaBoost.M1算法步骤
三 Python应用举例
四 AdaBoost.M1算法原理的进一步推导
之前文章袋装法和随机森林的思路是建立并列的一系列树构成“投票委员会”提高结果的准确性,集成学习的另一个策略是将一系列具有顺序相关的弱模型组成一个强模型,而不会有过拟合的问题。从弱模型到强模型的常见集成学习法有提升法(Boosting)和梯度提升树(Gradient Boosted Decision Tree,GBDT)等。本文主要介绍AdaBoost.M1提升算法。
AdaBoost算法(Adaptive Boosting)又称适应性提升法,主要用于解决输出变量仅有-1和+1两个类别时的分类预测问题。(SAMME算法将输出变量推广到多余2类)抽取训练集的Bootstrap方法点击这里查看。
开始时,每个样本被抽中的概率一样,即每个样本的权重相同:,然后进行如下的b=1,2,...,B次迭代,最终形成带有权重的联合委员会,产生最终预测结果:
说明: 为Bootstrap训练集,样本量为N。每次迭代产生的训练集中每个样本都会产生自己的权重(这里的权重即下次Bootstrap建立训练集时被抽到的概率)
说明:二分类随机猜测误差等于0.5,因此弱模型训练误差小于0.5;从上式可以看出,预测错误的样本,若其权重越大,则对误差的贡献也越大。I(·)为示性函数,当括号内条件成立时函数等于1,否则等于0.
说明:被错误预测的样本观测的权重是正确预测的倍(若预测正确则权重不变),此外,应满足,应是一个弱模型。可以看出,错误预测的而样本观测具有较高权重,在下次加权时有更大几率进入训练集,收到更多关注,因此每次迭代的模型具有顺序相关性。
上述每增加一次迭代,就会有一个新的弱模型加入“联合委员会”参与预测,这是向前分步可加建模(Forward Stagewise Additive Modeling)的具体体现,这类建模方法在迭代过程中会有新的成员不断进入“委员会”参与预测,先前进入的模型参数和权重不受后续进入模型的影响,且每次迭代仅需估计当前模型的参数和权重。
迭代结束时会有B 个弱模型组成的“联合委员会”,依据符号来确定的类别。
这里首先模拟生成800个数据,然后建立树深度为1的弱分类器作为提升法的基础学习器,并迭代500次,然后展示训练误差的变化。代码来自参考文献。
- # 需导入的模块
- import numpy as np
- import pandas as pd
- import warnings
- warnings.filterwarnings(action = 'ignore')
- import matplotlib.pyplot as plt
- %matplotlib inline
- plt.rcParams['font.sans-serif']=['SimHei'] #解决中文显示乱码问题
- plt.rcParams['axes.unicode_minus']=False
- from sklearn.model_selection import train_test_split,KFold,cross_val_score
- from sklearn import tree
- import sklearn.linear_model as LM
- from sklearn import ensemble
- from sklearn.datasets import make_classification,make_circles,make_regression
- from sklearn.metrics import zero_one_loss,r2_score,mean_squared_error,accuracy_score
- import xgboost as xgb
- # 提升法建模,计算各迭代次数下的训练误差
- N=800
- X,Y=make_circles(n_samples=N,noise=0.2,factor=0.5,random_state=123)
- unique_lables=set(Y)
- fig,axes=plt.subplots(nrows=1,ncols=2,figsize=(15,6))
- colors=plt.cm.Spectral(np.linspace(0,1,len(unique_lables)))
- markers=['o','*']
- for k,col,m in zip(unique_lables,colors,markers):
- x_k=X[Y==k]
- #plt.plot(x_k[:,0],x_k[:,1],'o',markerfacecolor=col,markeredgecolor="k",markersize=8)
- axes[0].scatter(x_k[:,0],x_k[:,1],color=col,s=30,marker=m)
- axes[0].set_title('%d个样本观测点的分布情况'%N)
- axes[0].set_xlabel('X1')
- axes[0].set_ylabel('X2')
- dt_stump = tree.DecisionTreeClassifier(max_depth=1, min_samples_leaf=1)
- B=500
- adaBoost = ensemble.AdaBoostClassifier(base_estimator=dt_stump,n_estimators=B,algorithm="SAMME",random_state=123)
- adaBoost.fit(X,Y)
- adaBoostErr = np.zeros((B,))
- for b,Y_pred in enumerate(adaBoost.staged_predict(X)):
- adaBoostErr[b] = zero_one_loss(Y,Y_pred)
- axes[1].plot(np.arange(B),adaBoostErr,linestyle='-')
- axes[1].set_title('迭代次数与训练误差')
- axes[1].set_xlabel('迭代次数')
- axes[1].set_ylabel('训练误差')
- # 图形化展示不同迭代次数下各样本观测的权重变化
- fig = plt.figure(figsize=(15,12))
- data=np.hstack((X.reshape(N,2),Y.reshape(N,1)))
- data=pd.DataFrame(data)
- data.columns=['X1','X2','Y']
- data['Weight']=[1/N]*N
- for b,Y_pred in enumerate(adaBoost.staged_predict(X)):
- data['Y_pred']=Y_pred
- data.loc[data['Y']!=data['Y_pred'],'Weight'] *= (1.0-adaBoost.estimator_errors_[b])/adaBoost.estimator_errors_[b]
- if b in [5,10,20,450]:
- axes = fig.add_subplot(2,2,[5,10,20,450].index(b)+1)
- for k,col,m in zip(unique_lables,colors,markers):
- tmp=data.loc[data['Y']==k,:]
- tmp['Weight']=10+tmp['Weight']/(tmp['Weight'].max()-tmp['Weight'].min())*100
- axes.scatter(tmp['X1'],tmp['X2'],color=col,s=tmp['Weight'],marker=m)
- axes.set_xlabel('X1')
- axes.set_ylabel('X2')
- axes.set_title("高权重的样本观测点(迭代次数=%d)"%b)
下面左图为模拟样本的情况,其中圆圈和五角星分别代表输出变量的两个类别,在使用树深度为1的弱学习器迭代500次后求出训练误差,右图显示在迭代次数上升时误差急剧下降,而后再缓慢下降,说明算法迭代效率高。
下图展示了不同迭代次数下高权重样本的分布情况,符号越大,代表下次Bootstrap倍抽样进入训练集的概率也就越大。可以看出:①较大的点都是之前弱模型没有预测正确的点,这些点基本集中在两类的边界处,②随着迭代次数增加,此特点愈发明显。
可见,AdaBoost.M1算法是一种最小化指数损失函数的向前分步可加建模方法。指数损失函数对参数估计值变化的敏感程度大于训练误差,应用更广泛。
《Python机器学习 数据建模与分析》,薛薇 等/著
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。