前言
依旧按照之前的博客路线来:介绍算法的基本原理和概念——>算法的拓展知识——->代码实现。
本节主要是介绍sklearn包中有关AdaBoost方法的使用。
包:sklearn.ensemble
组合技术通过聚集多个分类器的预测来提高分类准确率。
常用的组合分类器方法:
(1)通过处理训练数据集。
即通过处理某种抽样分布,对原始数据进行再抽样,得到多个训练集。
常用的方法有装袋(Bagging)和提升(boosting)(2)通过处理输入特征。
即通过选择输入特征的子集,形成每个训练集。适用于有大量荣予特征的数据集。
随机森林(Random forest)就是一种处理输入特征的组合方法(3)通过处理类标号。
适用于多分类的情况,将类标号随机划分成两个不相交的子集,再把问题变成二分类问题。
重复构建多次模型,进行分类投票。
常用的组合有:
BaggingClassifier: Bagging分类器组合
BaggingRegressor: Bagging回归器组合
AdaBoostClassifier: AdaBoost分类器组合
AdaBoostRegressor: AdaBoost回归器组合
GradientBoostingClassifier:GradientBoosting分类器组合
GradientBoostingRegressor: GradientBoosting回归器组合
ExtraTreeClassifier:ExtraTree分类器组合
ExtraTreeRegressor: ExtraTree回归器组合
RandomTreeClassifier:随机森林分类器组合
RandomTreeRegressor: 随机森林回归器组合
#例如:
from sklearn.ensemble import AdaBoostClassifier
from sklearn.tree import DecisionTreeClassifier
AdaBoostClassifier(DecisionTreeClassifier(max_depth=1),
algorithm="SAMME",
n_estimators=200)
解释:
装袋(Bagging):根据均匀概率分布从数据集中重复抽样(有放回).
算法思想:循环K次,每次都从样本集D中有放回地抽取样本集Di,这样总共得到k个样本集,用这K个样本集进行决策树生成,获得K个决策树模型,再将要检测的数据用这K个决策树模型进行多数表决,获得票数多的结论。
提升(Boosting):
算法思想:通过给样本设置不同的权值,每轮迭代给训练集中的元组重新分配权重,权重影响抽样,权重越大,越可能被抽取。迭代训练若干个分类器,在前一个分类器中被错误分类的元组被提高权重;最后由所有分类器一起投票(投票权重取决于分类器的准确率),决定分类。
不同的提升算法之间的差别是:(1)如何更新样本的权值;(2)如何组合每个分类器
其实,boosting算法是在bagging算法基础上的改进。boosting主要关注降低偏差,因此,boosting能基于泛化性能相当弱的学习构建出很强的集成;
Bagging主要关注降低方差,因此它在不剪枝的决策树、神经网络等学习器上效用更为明显。
偏差指的是算法的期望预测与真实预测之间的偏差程度,反映了模型本身的拟合能力
方差度量了同等大小的训练集的变动导致学习性能的变化,刻画了数据扰动所导致的影响。
另外,Boosting算法容易受到噪声的影响,这是因为在迭代过程中总是给噪声分配较大的权重,使得这些噪声在以后的迭代中受到更多的关注。Boosting算法也应该选择一个合适的迭代次数T,在某些情况下,迭代次数过多容易发生过拟合,可以用交叉验证找到合适的迭代次数。再者,算法运行速度较慢。
而我们常常听到的AdaBoost是Boosting发展到后来最具代表性的一类。所谓AdaBoost,即Adaptive Boosting,是指弱分类器根据学习到的结果反馈Adaptively调整假设的错误率,所以也不需要任何的先验知识就可以自主训练。下面主要介绍Adaboost算法的使用。
使用类:
class sklearn.ensemble.AdaBoostClassifier(base_estimator=None, n_estimators=50,learning_rate=1.0, algorithm='SAMME.R', random_state=None)
参数介绍:
base_estimator :(default=DecisionTreeClassifier) 选择哪种若分类器,scikit-learn中的分类器都可以
n_estimators :integer, (default=50) 最大迭代次数
learning_rate :float, (default=1.0) 迭代次数的每个弱分类器权重设置参数
algorithm : {‘SAMME’, ‘SAMME.R’},(default=’SAMME.R’) ’SAMME.R’的话弱分类器需要支持概率预测,比如逻辑回归;‘SAMME’这个是针对离散的变量。
类中方法:
fit(X, y[, sample_weight])
predict(X)
predict_proba(X)
score(X, y[, sample_weight])
python实现一
# -*- encoding:utf-8 -*-
#导入模型估计方法,交叉验证
from sklearn.model_selection import cross_val_score
#导入数据集包,sklearn中自带数据
from sklearn.datasets import load_iris
#导入AdaBoostClassifier类
from sklearn.ensemble import AdaBoostClassifier
#导入决策树和贝叶斯分类
from sklearn.tree import DecisionTreeClassifier
from sklearn.naive_bayes import MultinomialNB
iris=load_iris()#下载数据集
###调用AdaBoost算法
'''
弱学习器的个数,通过参数n_estimators来控制。
learning_rate参数控制着在最终聚合时弱学习器的贡献。
缺省情况下,弱学习器都是单层决策树(decesion stumps)。
不同的弱学习器类型可以通过base_estimator参数来指定。
想要获得理想的结果,需要调整最主要的参数是,n_estimators以及base estimator的复杂度
(比如:在决策树下:深度:max_depth,或者 所需要的最小样本个数:min_samples_leaf)
'''
clf=AdaBoostClassifier(DecisionTreeClassifier(max_depth=1), algorithm='SAMME.R',n_estimators=100)#迭代100次,迭代多少次就会产生多少个弱分类器
#拟合AdaBoost模型
clf.fit(iris.data,iris.target)
#print set(iris.target)共三类
#输出每个特征的权重,可以用于特征选择
print clf.feature_importances_
scores=cross_val_score(clf,iris.data,iris.target)#分类器的精确度 # #to use the default 3-fold cross validation
print '分类器的精度为:',scores.mean()
#预测
print clf.predict([[4.4, 2.9, 1.4, 0.2],[5.9, 3.0, 5.1, 1.8]])
print clf.predict_proba([[4.4, 2.9, 1.4, 0.2],[5.9, 3.0, 5.1, 1.8]])
#调用贝叶斯算法
clf=MultinomialNB()
scores=cross_val_score(clf,iris.data,iris.target)
print '分类器的精度为:',scores.mean()
python实现二
几种方法的比较
# -*- encoding:utf-8 -*-
'''
本例是Sklearn网站上的关于决策树桩、决策树、
和分别使用AdaBoost—SAMME和AdaBoost—SAMME.R的AdaBoost算法
在分类上的错误率。
这个例子基于Sklearn.datasets里面的make_Hastie_10_2数据库。
取了12000个数据,其他前10000个作为训练集,后面2000个作为了测试集。
'''
import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import zero_one_loss
from sklearn.ensemble import AdaBoostClassifier
import time
a=time.time()
n_estimators=400
learning_rate=1.0
X,y=datasets.make_hastie_10_2(n_samples=12000,random_state=1)
X_test,y_test=X[10000:],y[10000:]
X_train,y_train=X[:2000],y[:2000]
#决策树桩
dt_stump=DecisionTreeClassifier(max_depth=1,min_samples_leaf=1)
dt_stump.fit(X_train,y_train)
dt_stump_err=1.0-dt_stump.score(X_test,y_test)
#决策树
dt=DecisionTreeClassifier(max_depth=9,min_samples_leaf=1)
dt.fit(X_train,y_train)
dt_err=1.0-dt.score(X_train,y_test)
ada_discrete=AdaBoostClassifier(base_estimator=dt_stump,learning_rate=learning_rate,
n_estimators=n_estimators,algorithm='SAMME')
ada_discrete.fit(X_train,y_train)
ada_real=AdaBoostClassifier(base_estimator=dt_stump,learning_rate=learning_rate,
n_estimators=n_estimators,algorithm='SAMME.R')#相比于ada_discrete只改变了Algorithm参数
ada_real.fit(X_train,y_train)
fig=plt.figure()
ax=fig.add_subplot(111)
ax.plot([1,n_estimators],[dt_stump_err]*2,'k-',label='Decision Stump Error')
ax.plot([1,n_estimators],[dt_err]*2,'k--',label='Decision Tree Error')
ada_discrete_err=np.zeros((n_estimators,))
for i,y_pred in enumerate(ada_discrete.staged_predict(X_test)):
ada_discrete_err[i]=zero_one_loss(y_pred,y_test)#0-1损失,类似于指示函数
ada_discrete_err_train=np.zeros((n_estimators,))
for i,y_pred in enumerate(ada_discrete.staged_predict(X_train)):
ada_discrete_err_train[i]=zero_one_loss(y_pred,y_train)
ada_real_err=np.zeros((n_estimators,))
for i,y_pred in enumerate(ada_real.staged_predict(X_test)):
ada_real_err[i]=zero_one_loss(y_pred,y_test)
ada_real_err_train=np.zeros((n_estimators,))
for i,y_pred in enumerate(ada_real.staged_predict(X_train)):
ada_discrete_err_train[i]=zero_one_loss(y_pred,y_train)
ax.plot(np.arange(n_estimators)+1,ada_discrete_err,label='Discrete AdaBoost Test Error',color='red')
ax.plot(np.arange(n_estimators)+1,ada_discrete_err_train,label='Discrete AdaBoost Train Error',color='blue')
ax.plot(np.arange(n_estimators)+1,ada_real_err,label='Real AdaBoost Test Error',color='orange')
ax.plot(np.arange(n_estimators)+1,ada_real_err_train,label='Real AdaBoost Train Error',color='green')
ax.set_ylim((0.0,0.5))
ax.set_xlabel('n_estimators')
ax.set_ylabel('error rate')
leg=ax.legend(loc='upper right',fancybox=True)
leg.get_frame().set_alpha(0.7)
b=time.time()
print 'total running time of this example is :',(b-a)
plt.show()
实验结果为:
从图中可以看出:弱分类器(Decision Tree Stump)单独分类的效果很差,错误率将近50%,强分类器(Decision Tree)的效果要明显好于他。但是AdaBoost的效果要明显好于这两者。同时在AdaBoost中,Real AdaBoost的分类效果更佳好一点。
下一节我们将要用Python实现一个简单的AdaBoost算法,一步一步慢慢来吧。
《完》
所谓的不平凡就是平凡的N次幂。
---By Ada