集成学习

通俗讲解集成学习算法(原文来自Datawhale团队)

集成学习

集成学习,即分类器集成,通过构建并结合多个学习器来完成学习任务。一般结构是:先产生一组“个体学习器”,也称为“弱学习器”,再用某种策略将它们结合起来。结合策略主要有平均法、投票法和学习法等。集成学习(ensemble learning)通过构建并结合多个学习器来完成学习任务,有时也被称为多分类器系统(multi-classifier system)、基于委员会的学习(committee-based learning)。

集成学习是这样一个过程,按照某种算法生成多个模型,如分类器或者称为专家,再将这些模型按照某种方法组合在一起来解决某个智能计算问题。集成学习主要用来提高模型(分类、预测、函数估计)的性能,或者是用来降低模型选择不当的可能性。集成算法本身是一种监督学习算法,因为它可以被训练然后进行预测,组合的多个模型作为整体代表一个假设(hypothesis)。

集成方法是将几种机器学习技术组合成一个预测模型的元算法,以达到减小方差(bagging)、偏差(boosting)或改进预测(stacking)的效果。

分类器

分类器是数据挖掘中对样本进行分类的方法的统称,包含决策树、逻辑回归、朴素贝叶斯、神经网络等算法。分类是数据挖掘的一种非常重要的方法。分类的概念是在已有数据的基础上学会一个分类函数或构造出一个分类模型。该函数或模型能够把数据库中的数据记录映射到给定类别中的某一个,从而可以应用于数据预测。

分类器的构造和实施大体会经过以下几个步骤:

  • 选定样本(包含正样本和负样本),将所有样本分成训练样本和测试样本两部分;
  • 在训练样本上执行分类器算法,生成分类模型;
  • 在测试样本上执行分类模型,生成预测结果;
  • 根据预测结果,计算必要的评估指标,评估分类模型的性能。
1.决策树分类器

构造这个分类器不需要任何领域的知识,也不需要任何的参数设置。因此它特别适合于探测式的知识发现。此外,这个分类器还可以处理高维数据,而且采用的是类似于树这种形式,也特别直观和便于理解。因此,决策树时许多商业规则归纳系统的基础。

2.朴素贝叶斯分类器

朴素贝叶斯分类器是假设数据样本特征完全独立,以贝叶斯定理为基础的简单概率分类器。

3.AdaBoost算法

AdaBoost算法的自适应在于前一个分类器产生的错误分类样本会被用来训练下一个分类器,从而提升分类准确率,但是对于噪声样本和异常样本比较敏感。

4.支持向量机

支持向量机是用构建一个或多个高维的超平面来将样本数据进行划分,超平面即为样本之间的分类边界。

5.K近邻算法

基于K近邻的K个样本作为分析从而简化计算提升效率,K近邻算法分类器是基于距离计算的分类器。

集成学习方法

集成学习有许多集成模型,例如自助法、自助聚合(Bagging)、随机森林、提升法(Boosting)、堆叠法(stacking)以及许多其它的基础集成学习模型。

集成方法的思想是通过将这些个体学习器(弱学习器)的偏置和/或方差结合起来,从而创建一个强学习器(或集成模型),从而获得更好的性能。
有如下三种主要的旨在组合弱学习器的元算法:

  • 自助聚合(Bagging),该方法通常考虑的是同质弱学习器,相互独立地并行学习这些弱学习器,并按照某种确定性的平均过程将它们组合起来。
  • 提升法(Boosting),该方法通常考虑的也是同质弱学习器。它以一种高度自适应的方法顺序地学习这些弱学习器(每个基础模型都依赖于前面的模型),并按照某种确定性的策略将它们组合起来。
  • 堆叠法(Stacking),该方法通常考虑的是异质弱学习器,并行地学习它们,并通过训练一个元模型将它们组合起来,根据不同弱模型的预测结果输出一个最终的预测结果。

可以认为,Bagging的重点在于获得一个方差比其组成部分更小的集成模型,而Boosting和Stacking则将主要生成偏置比其组成部分更低的强模型。

1.自助聚合(Bagging)(基于bagging思想的套袋集成技术)

在并行化的方法中,我们单独拟合不同的学习器,因此可以同时训练它们。最著名的方法是自助聚合(Bagging),它的目标是生成比单个模型更棒的集成模型。
套袋方法是由柳·布莱曼在1994年的技术报告中首先提出并证明了套袋方法可以提高不稳定模型的准确度的同时降低过拟合的程度(可降低方差)
Bagging方法是使用全部样本的一个随机抽样,每个分类器都是使用不同的样本进行训练。

Bagging的实现方法:
#基于bagging思想的套袋集成技术
#套袋方法可以提高不稳定模型的准确度的同时降低过拟合程度
#投票机制在训练每个分类器时都是用相同的全部样本,而bagging方法则是使用全部样本的一个随机抽样,每个
#分类器都是使用不同的样本进行训练,其他都是跟投票方法一模一样

from sklearn.model_selection import train_test_split  #划分训练集和测试集
from sklearn.preprocessing import StandardScaler #标准化数据
from sklearn.preprocessing import LabelEncoder #标签化分类变量
from sklearn.model_selection import cross_val_score #10折交叉验证评价模型
from sklearn.linear_model import  LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import  KNeighborsClassifier
from sklearn.pipeline import  Pipeline #管道简化工作流
from sklearn.ensemble import VotingClassifier
from sklearn.metrics import  roc_curve,auc,accuracy_score
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.ensemble import BaggingClassifier

df_wine=pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)
df_wine.columns=['Class label','Alcohol','Malic acid','Ash','Alcalinity of ash','Magnesium','Total phenols',
                 'Flavanoids','Nonflavanoid phenols','Proanthocyanins','Color intensity','Hue',
                 'OD280/OD315 of diluted wines','Proline']
df_wine=df_wine[df_wine['Class label']!=1]
y=df_wine['Class label'].values
X=df_wine[['Alcohol','OD280/OD315 of diluted wines']].values
le=LabelEncoder()
y=le.fit_transform(y)
x_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=1,stratify=y)
#使用单一决策树分类
tree=DecisionTreeClassifier(criterion='entropy',random_state=1,max_depth=None)
tree=tree.fit(x_train,y_train)
y_train_pred=tree.predict(x_train)
y_test_pred=tree.predict(x_test)
tree_train=accuracy_score(y_train,y_train_pred)
tree_test=accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies %.3f/%.3f'%(tree_train,tree_test))

#使用BaggingClassifier分类
bag=BaggingClassifier(base_estimator=tree,n_estimators=500,max_samples=1.0,max_features=1.0,
                      bootstrap=True,bootstrap_features=False,n_jobs=1,random_state=1)
bag=bag.fit(x_train,y_train)
y_train_pred=bag.predict(x_train)
y_test_pred=bag.predict(x_test)
bag_train=accuracy_score(y_train,y_train_pred)
bag_test=accuracy_score(y_test,y_test_pred)
print('BaggingClassifier train/test accuracies %.3f/%.3f'%(bag_train,bag_test))

2.提升法(Boosting)

在顺序化的方法中,组合起来的不同弱模型之间不再相互独立地拟合。其思想是迭代地拟合模型,使模型在给定步骤上的训练依赖于之前的步骤上拟合的模型。提升法是这些方法中最著名的一种,它生成的集成模型通常比组成该模型的弱学习器偏置更小。
Boosting和Bagging的工作思路是一样的:我们构建一系列模型,将它们聚合起来得到一个性能更好的强学习器。然而,其重点在于减小方差的Bagging不同,Boosting着眼于以一种适应性很强的方式顺序拟合多个弱学习器,序列中每个模型在拟合的过程中,会更加重视那些序列中之前的模型处理地很糟糕的观测数据。
直观地说,每个模型都把注意力集中在目前最难拟合的观测数据上,这样一来,在这个过程的最后,我们就获得了一个具有较低偏置的强学习器,和Bagging一样,Boosting也可以用于回归和分类问题。由于其重点在于减小偏置,用于Boosting的基础模型通常是那些低方差高偏置的模型。例如,如果想要使用树作为基础模型,我们将主要选择只有少许几层的较浅决策树。而选择低方差高偏置模型作为Boosting弱学习器的另一个重要原因是:这些模型拟合的计算开销较低。实际上,由于拟合不同模型的计算无法并行处理,顺序地拟合若干复杂模型会导致计算开销变得非常高。
一旦选定了弱学习器,我们仍需要定义它们的拟合方式和聚合方式。主要有两种重要的Boosting算法可供选择:自适应提升(adaboost)和梯度提升(gradient boosting)。
这两种元算法在顺序化的过程中创建和聚合弱学习器的方式存在差异。自适应提升算法会更新附加给每个训练数据集中观测数据的权重,而梯度提升算法则会更新这些观测数据的值,这里产生差异的主要原因是:两种算法解决优化问题(寻找最佳模型——弱学习器的加权和)的方式不同。

Boosting的实现方法:
#基于boosting思想的自适应增强方法
#与Bagging相比,Boosting思想可以降低偏差

from sklearn.model_selection import train_test_split  #划分训练集和测试集
from sklearn.preprocessing import StandardScaler #标准化数据
from sklearn.preprocessing import LabelEncoder #标签化分类变量
from sklearn.model_selection import cross_val_score #10折交叉验证评价模型
from sklearn.linear_model import  LogisticRegression
from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import  KNeighborsClassifier
from sklearn.pipeline import  Pipeline #管道简化工作流
from sklearn.ensemble import VotingClassifier
from sklearn.metrics import  roc_curve,auc,accuracy_score
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import AdaBoostClassifier
import numpy as np

df_wine=pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/wine/wine.data',header=None)
df_wine.columns=['Class label','Alcohol','Malic acid','Ash','Alcalinity of ash','Magnesium','Total phenols',
                 'Flavanoids','Nonflavanoid phenols','Proanthocyanins','Color intensity','Hue',
                 'OD280/OD315 of diluted wines','Proline']
df_wine=df_wine[df_wine['Class label']!=1]
y=df_wine['Class label'].values
X=df_wine[['Alcohol','OD280/OD315 of diluted wines']].values
le=LabelEncoder()
y=le.fit_transform(y)
x_train,x_test,y_train,y_test=train_test_split(X,y,test_size=0.2,random_state=1,stratify=y)
#使用单一决策树分类
tree=DecisionTreeClassifier(criterion='entropy',random_state=1,max_depth=None)
tree=tree.fit(x_train,y_train)
y_train_pred=tree.predict(x_train)
y_test_pred=tree.predict(x_test)
tree_train=accuracy_score(y_train,y_train_pred)
tree_test=accuracy_score(y_test,y_test_pred)
print('Decision tree train/test accuracies %.3f/%.3f'%(tree_train,tree_test))

#使用Adaboost集成建模
ada=AdaBoostClassifier(base_estimator=tree,n_estimators=500,learning_rate=0.1,random_state=1)
ada=ada.fit(x_train,y_train)
y_train_pred=ada.predict(x_train)
y_test_pred=ada.predict(x_test)
ada_train=accuracy_score(y_train,y_train_pred)
ada_test=accuracy_score(y_test,y_test_pred)
print('AdaBoost train/test accuracies %.3f/%.3f'%(ada_train,ada_test))

#观察决策树与Adaboost异同
x_min=x_train[:,0].min()-1
x_max=x_train[:,0].max()+1
y_min=x_train[:,1].min()-1
y_max=x_train[:,1].max()+1
xx,yy=np.meshgrid(np.arange(x_min,x_max,0.1),np.arange(y_min,y_max,0.1))
f,axarr=plt.subplots(nrows=1,ncols=2,sharex='col',sharey='row',figsize=(12,6))
for idx,clf,tt in zip([0,1],[tree,ada],['Decision tree','Adaboost']):
    clf.fit(x_train,y_train)
    z=clf.predict(np.c_[xx.ravel(),yy.ravel()])
    z=z.reshape(xx.shape)
    axarr[idx].contourf(xx,yy,z,alpha=0.3)
    axarr[idx].scatter(x_train[y_train==0,0],x_train[y_train==0,1],c='blue',marker='^')
    axarr[idx].scatter(x_train[y_train==1, 0], x_train[y_train == 1, 1], c='red', marker='o')
    axarr[idx].set_title(tt)
axarr[0].set_ylabel('Alcohol',fontsize=12)
plt.tight_layout()
plt.text(0,-0.2,s='OD280/OD315 of diluted wines',ha='center',va='center',fontsize=12,transform=axarr[1].transAxes)
plt.show()

3.堆叠法(Stacking)

堆叠法与Bagging和Boosting主要存在两方面的差异。首先,堆叠法通常考虑的是异质弱学习器(不同的学习算法被组合在一起),而Bagging和Boosting主要考虑的是同质弱学习器。其次,stacking堆叠法学习用元模型组合基础模型,而Bagging和Boosting则根据确定性算法组合弱学习器。
正如上文已经提到的,堆叠法的概念是学习几个不同的弱学习器,并通过训练一个元模型来组合它们,然后基于这些弱模型返回的多个预测结果输出最终的预测结果。
因此,为了构建Stacking模型,需要定义两个东西:想要拟合的L个学习器以及组合它们的元模型。例如,对于分类问题来说,我们可以选择KNN分类器、logistic回归和SVM作为弱学习器,并决定学习神经网络作为元模型。然后,神经网络将会把三个弱学习器的输出作为输入,并返回基于该输入的最终预测。所以,假设我们想要拟合由L个弱学习器组成的Stacking集成模型。我们必须遵循以下步骤:

  • 将训练数据分为两组
  • 选择L个弱分类器,用它们拟合第一组数据
  • 使L个学习器中的每个学习器对第二组数据中的观测数据进行预测
  • 在第二组数据上拟合元模型,使用弱学习器做出的预测作为输入
Stacking的实现方法:
#分层模型集成框架stacking(叠加算法)

#简单堆叠3折CV分类
from sklearn import datasets
from sklearn.model_selection import cross_val_score,GridSearchCV
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.ensemble import  RandomForestClassifier
from mlxtend.classifier import StackingCVClassifier
from mlxtend.plotting import plot_decision_regions
import matplotlib.gridspec as gridspec
import itertools
import matplotlib.pyplot as plt

iris=datasets.load_iris()
X,y=iris.data[:,1:3],iris.target
RANDOM_SEED=42
# clf1=KNeighborsClassifier(n_neighbors=1)
# clf2=RandomForestClassifier(random_state=RANDOM_SEED)
# clf3=GaussianNB()
# lr=LogisticRegression()
#
# sclf=StackingCVClassifier(classifiers=[clf1,clf2,clf3],meta_classifier=lr,random_state=RANDOM_SEED)
# print('3-fold cross validation:\n')
# for clf,label in zip([clf1,clf2,clf3,sclf],['KNN','Random Forest','Naive Bayes','Stack']):
#     scores=cross_val_score(clf,X,y,cv=3,scoring='accuracy')
#     print("Accuract:%0.2f(+/- %0.2f)[%s]"%(scores.mean(),scores.std(),label))
# #画出决策边界
# gs=gridspec.GridSpec(2,2)
# fig=plt.figure(figsize=(10,8))
# for clf,lab,grd in zip([clf1,clf2,clf3,sclf],['KNN','Random Forest','Naive Bayes','Stack'],
#                        itertools.product([0,1],repeat=2)):
#     clf.fit(X,y)
#     ax=plt.subplot(gs[grd[0],grd[1]])
#     fig=plot_decision_regions(X=X,y=y,clf=clf)
#     plt.title(lab)
# plt.show()

#使用概率作为元特征
# clf1=KNeighborsClassifier(n_neighbors=1)
# clf2=RandomForestClassifier(random_state=RANDOM_SEED)
# clf3=GaussianNB()
# lr=LogisticRegression()
#
# sclf=StackingCVClassifier(classifiers=[clf1,clf2,clf3],use_probas=True,meta_classifier=lr,random_state=RANDOM_SEED)
# print('3-fold cross validation:\n')
# for clf,label in zip([clf1,clf2,clf3,sclf],['KNN','Random Forest','Naive Bayes','Stack']):
#     scores=cross_val_score(clf,X,y,cv=3,scoring='accuracy')
#     print("Accuract:%0.2f(+/- %0.2f)[%s]"%(scores.mean(),scores.std(),label))
#堆叠5折CV分类与网格搜索(结合网格搜索调参优化):
clf1=KNeighborsClassifier(n_neighbors=1)
clf2=RandomForestClassifier(random_state=RANDOM_SEED)
clf3=GaussianNB()
lr=LogisticRegression()

sclf=StackingCVClassifier(classifiers=[clf1,clf2,clf3],meta_classifier=lr,random_state=RANDOM_SEED)
params={'kneighborsclassifier__n_neighbors':[1,5],
        'randomforestclassifier__n_estimators':[10,50],
        'meta_classifier__C':[0.1,10.0]}
grid=GridSearchCV(estimator=sclf,param_grid=params,cv=5,refit=True)
grid.fit(X,y)
cv_keys=('mean_test_score','std_test_score','params')
for r,_ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.2f %r"%(grid.cv_results_[cv_keys[0]][r],
                                grid.cv_results_[cv_keys[1]][r]/2.0,
                                grid.cv_results_[cv_keys[2]][r]))
print("Best parameters:%s"%grid.best_params_)
print('Accuracy:%.2f'%grid.best_score_)
附:深度学习中的集成学习

此外在深度学习中本身还有一些集成学习思路的做法,值得借鉴学习:

  • 丢弃法Dropout
  • 测试集数据扩增TTA
  • Snapshot
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值