集成学习通过构建并结合多个学习器来完成学习任务,也被称为多分类器系统。集成学习就是将多个“学习器”通过某种策略结合起来。个体学习器通常由一个现有的学习算法从数据中产生,由单一种类的学习器集成的是“同质”的,由不同种类的学习器集成是“异质”的,同质集成中的个体称为“基学习器”。
集成学习通过组合多个学习期来获得比单个个体学习期显著优越的泛化性能。根据个体学习器的生成方式大概可以分为以下两类:
(1)Boosting算法:在这类算法中,个体学习器之间存在强依赖关系,必须串行生成
(2)Bagging算法:在这类算法中,个体学习器之间不必存在强依赖关系,可以同时生成
Boost算法步骤如下:
(1)首先从初始训练集得到一个基学习器
(2)根据基学习器的表现对训练样本的权重进行调整,使得先前被基学习器误判的训练样本在后续受到更多的关注
(3)然后基于调整后的样本权重来训练下一个基学习器
(4)一直重复,直到达到基学习器的指定上限或者已经完美的训练好
(5)最终将这些基学习器进行加权组合得到集成学习器
这里我主要介绍Boosting算法里面最具有代表性的AdaBoost算法。
AdaBoost算法最核心的两个步骤就是权值调整和基分类器组合。
权值调整:AdaBoost算法提高了那些被上一轮分类器错误分类的样本权值,降低了正确分类的权值,这样使得上一轮被分类错误的在下一轮受到了更大的重视。
基分类器组合:组合采取线性加权的方式,加大了分类错误率较小的基分类器的权重,减小分类误差较大的基分类器的权重。
AdaBoost算法如下:
输入:训练集,基分类器(比如决策树,贝叶斯等)
输出:集成分类器
算法步骤:
(1) 初始化训练数据的权重
(2) 使用具有权重向量的数据集学习,得到一个学习器
(3) 计算这个学习器在训练集上的错误率
注意:这里要求错误率要小于0.5
(4) 计算这个分类器在集成分类器中的权重
(5) 更新下一次训练集的权重向量
其中它保证了更新后的权重是一个概率分布。
(6) 构建基本分类器的线性组合
关于第三步为何错误率一定要小于0.5的解释:
AdaBoost算法是通过降低正确分类样本的权重,提高错误分类样本的权重来实现提升分类器性能,这个权重是通过每一轮的权重更新实现的。
假定正确为1,错误为-1,那么对于分类正确的样本,那么下一轮的权重为:
对于分类错误的样本,在下一轮的权重为:
比较两者的大小,很明显用比做除法比做差法更直接,通过比较两者的商,可以发现分类错误的样本权重与分类正确的样本权重之商为:
因此得出错误率必须小于0.5。
下面是算法的效果展示,这里用sklearn库里的AdaBoost算法。数据集是它自带的手写识别数据集Digit Dataset。
AdaBoostClassifier(base_estimator=None,n_estimators=50,
learning_rate=1.0,algorithm="SAMME.R",random_state=None)
参数说明:
base_estimator:一个基础分类器对象,默认为决策树分类,这类分类器必须支持带样本权重的学习
n_estimators:一个整数,指定基础分类器的上限数目,默认是50,若提前训练好,则分类器
数目可以小于该值
learning_rate:步长,通常该值越小,需要的基础分类器越多。Hm(X)=Hm-1(X)+vah(x),它就
是这里的v
algorithm:是一个字符串,指定算法,该算法用于多分类问题
"SAMME.R":使用SAMME.R算法。基础分类器必须支持计算类别的概率
"SAMME":使用SAMME算法
random_state:一个整数,或者一个RandomState实例,或者None
如果为整数,则它指定的随机数生成器的种子
如果为实例,则指定随机数生成器
如果为None,使用默认的随机数生成器
import matplotlib.pyplot as plt
import numpy as np
from sklearn import datasets,cross_validation,ensemble,naive_bayes
#用于回归的数据集
def load_data_regression():
diabetes=datasets.load_diabetes()
return cross_validation.train_test_split(diabetes.data,diabetes.target,
test_size=0.25,random_state=0)
#用于分类的数据集
def load_data():
digits=datasets.load_digits()
return cross_validation.train_test_split(digits.data,digits.target,test_size=0.25,
random_state=0)
def test_GaussianNB(*data):
X_train,X_test,y_train,y_test=data
cls=naive_bayes.GaussianNB()
cls.fit(X_train,y_train)
print("train score:%.2f"%(cls.score(X_train,y_train)))
print("test score:%.2f"%(cls.score(X_test,y_test)))
def test_AdaBoostClassifier(*data):
X_train,X_test,y_train,y_test=data
clf=ensemble.AdaBoostClassifier(learning_rate=0.1,
base_estimator=naive_bayes.GaussianNB(),
n_estimators=100)
clf.fit(X_train,y_train)
##绘图
fig=plt.figure()
ax=fig.add_subplot(1,1,1)
estimators_num=len(clf.estimators_)
X=range(1,estimators_num+1)
ax.plot(list(X),list(clf.staged_score(X_train,y_train)),label="Train score")
ax.plot(list(X),list(clf.staged_score(X_test,y_test)),label="Test score")
ax.set_xlabel("estimator num")
ax.set_ylabel("score")
ax.legend(loc="best")
ax.set_title("AdaBoostClassifier")
plt.show()
print("Train score:%f"%(clf.score(X_train,y_train)))
print("Test score:%f"%(clf.score(X_test,y_test)))
if __name__=="__main__":
X_train,X_test,y_train,y_test=load_data()
test_GaussianNB(X_train,X_test,y_train,y_test)
test_AdaBoostClassifier(X_train,X_test,y_train,y_test)
根据代码运行的效果的,单个高斯贝叶斯分类器训练正确率0.85746,测试集正确率0.83333.采用集成学习之后的贝叶斯分分类器训练正确率0.91239,测试集正确率0.88222.