sklearn集成学习

sklearn集成学习有一些特别著名的集成方法,包括 bagging, boosting, stacking,下面我们逐一介绍。

集成学习的数学原理

模型方差与偏差关系

模型的偏差是训练出来的模型在训练集上的准确度(即在样本上拟合的好不好)。模型的方差是训练出来的模型在测试集上的准确度(即预测的准不准)。方差越大的模型越容易过拟合。
通常来说弱模型是偏差高(在训练集上准确度低)方差小(防止过拟合能力强)的模型。强模型是偏差低(在训练集上准确度高)方差高(防止过拟合能力弱)的模型。bagging和stacking中的基模型为强模型,boosting中的基模型为弱模型。bagging和stacking中的基模型为强模型是偏差低(在训练集上准确度高)方差高(防止过拟合能力弱),boosting中的基模型为弱模型。
方差,偏差,误差与模型复杂度关系。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

一、集成方法bagging

(基模型为强模型,bagging的训练过程旨在降低方差)

bagging:从训练集又放回的 进行子抽样组成每个基模型所需要的子训练集,数据集允许重复,对所有基模型预测的结果进行综合产生最终的预测结果,基模型为强模型,是偏差低(在训练集上准确度高)方差高(防止过拟合能力弱)。

Bagging对样本重采样,对每一重采样得到的子样本集训练一个模型,最后取平均。由于子样本集的相似性以及使用的是同种模型,因此各模型有近似相等的bias和variance(事实上,各模型的分布也近似相同,但不独立)。由于,所以bagging后的bias和单个子模型的接近,一般来说不能显著降低bias。整体模型的期望近似于基模型的期望,这也就意味着整体模型的偏差和基模型的偏差近似。同时,整体模型的方差小于等于基模型的方差(当各个模型相同的时候取等号)。

对于bagging来说,整体模型的偏差和基模型近似,整体模型的方差随着基模型数(m)的增多而减少,从而防止过拟合的能力增强,方差降低,模型的准确度得到提高

主要算法

随机森林(Bagging + 决策树 )

sklearn实现

sklearn中的sklearn.ensemble.BaggingClassifier(分类)可以实现Bagging

sklearn.ensemble.BaggingClassifier(base_estimator=None, n_estimators=10, max_samples=1.0, max_features=1.0, bootstrap=True, bootstrap_features=False, oob_score=False, warm_start=False, n_jobs=None, random_state=None, verbose=0)

参数说明:

  • n_estimators:基学习器的数量
  • max_samples:每个基学习器中的样本数,如果是整形,则就是样本个数;如果是float,则是样本个数占所有训练集样本个数的比例
  • bootstrap :是否采用有放回抽样(bagging),为True表示采用,否则为pasting。默认为True
  • n_jobs:并行运行的作业数量。-1时,个数为处理器核的个数
  • oob_socre:为True时,对模型进行out-of-bag的验证,即在一个基学习器中,没有用于训练的数据用于验证

相对于单个的决策树,Bagging方法得到的分类边界更加平滑相对于pasting方法来说,bagging方法中模型的偏差会偏大一点,因为它是采用有放回的抽样,所有模型中用到的数据的均匀性会差一点;但是因为这样,模型之间相对独立一点,因此bagging的方差会小一点。在实际使用过程中,bagging的效果一般会更好,因此一般使用bagging。但是对于具体的问题,我们也可以用交叉验证验证两种模型的性能。

# 产生样本数据集
from sklearn.model_selection import cross_val_score
from sklearn import datasets
from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier

iris = datasets.load_iris()
X, y = iris.data, iris.target


print ('==================Bagging 元估计器============')

bagging = BaggingClassifier(KNeighborsClassifier(),max_samples=0.5, max_features=0.5,oob_score=True)
scores = cross_val_score(bagging, X, y)
bagging.fit(X, y)
print('Bagging准确率:',scores.mean())
print (bagging.estimators_features_)
print (bagging.oob_score_)

二、集成方法boosting

(基模型为弱模型,boosting的训练过程旨在降低偏差)

boosting:训练过程为阶梯状,基模型按次序一一进行训练(实现上可以做到并行),基模型的训练集按照某种策略每次都进行一定的转化。对所有基模型预测的结果进行线性综合产生最终的预测结果。

基模型为弱模型,是偏差高(在训练集上准确度低)方差低(防止过拟合能力强)。若基模型不是弱模型,其方差相对较大,这将导致整体模型的方差很大,即无法达到防止过拟合的效果。因此,boosting框架中的基模型必须为弱模型。

对于boosting来说,整体模型的初始偏差较高(在训练集上准确度低),方差较低(防止过拟合能力强),随着基模型数的增多,整体模型的期望值增加,偏差减少,更接近真实值,因此,整体模型的准确度提高。当训练过度时,因方差增高,整体模型的准确度反而降低。

主要算法

提升树(AdaBoost + 决策树 )
AdaBoost
GBDT(由Gradient Boosting + 决策树 合成而来)( 以CART作为基分类器)
xgboost

Boosting与Bagging的不同之处:

1、Bagging的训练集是随机的,所有样本的权重一直不变,以独立同分布选取的训练样本子集训练弱分类器,Bagging 平等看待每个样本,而Boosting训练集的选择不是独立的,每一次选择的训练集都依赖于上一次学习的结果,根据错误率取样,虽然是每次随机抽样,但对分的不好的样本,加大权重,再进行训练。,所以新的分类器将会把“注意力”放在这些不太好分类的样本上。因此Boosting的分类精度在大多数数据集中要优于Bagging,但是在有些数据集中,由于过拟合的原因,Boosting的精度会退化。
2、Bagging的每个预测函数(即弱假设)没有权重,而Boosting根据每一次训练的训练误差得到该次预测函数的权重;
3、Bagging致力于减少variance,而Boosting致力于减少bias。
4、Bagging 在训练过程中是并行训练。Boosting 在训练过程是串行训练的。
在这里插入图片描述

# 产生样本数据集
from sklearn.model_selection import cross_val_score
from sklearn import datasets
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import RandomForestClassifier
iris = datasets.load_iris()
X, y = iris.data, iris.target
 
print ('# ====================AdaBoost=========================')

clf = AdaBoostClassifier(n_estimators=100)
scores = cross_val_score(clf, X, y)
clf.fit(X, y)
print('AdaBoost准确率:',scores.mean())
print (clf.estimator_weights_)
print (clf.estimator_errors_)

三、集成方法stacking(基模型为强模型)

stacking:将训练好的所有基模型对训练基进行预测,第j个基模型对第i个训练样本的预测值将作为新的训练集中第i个样本的第j个特征值,最后基于新的训练集进行训练。同理,预测的过程也要先经过所有基模型的预测形成新的测试集,最后再对测试集进行预测。
在这里插入图片描述
上半部分是用一个基础模型进行5折交叉验证,如:用XGBoost作为基础模型Model1,5折交叉验证就是先拿出四折作为training data,另外一折作为testing data。注意:在stacking中此部分数据会用到整个traing set。如:假设我们整个training set包含10000行数据,testing set包含2500行数据,那么每一次交叉验证其实就是对training set进行划分,在每一次的交叉验证中training data将会是8000行,testing data是2000行。

每一次的交叉验证包含两个过程,1. 基于training data训练模型;2. 基于training data训练生成的模型对testing data进行预测。在整个第一次的交叉验证完成之后我们将会得到关于当前testing data的预测值,这将会是一个一维2000行的数据,记为a1注意!在这部分操作完成后,我们还要对数据集原来的整个testing set进行预测,这个过程会生成2500个预测值,这部分预测值将会作为下一层模型testing data的一部分,记为b1。因为我们进行的是5折交叉验证,所以以上提及的过程将会进行五次,最终会生成针对testing set数据预测的5列2000行的数据a1,a2,a3,a4,a5,对testing set的预测会是5列2500行数据b1,b2,b3,b4,b5。

在完成对Model1的整个步骤之后,我们可以发现a1,a2,a3,a4,a5其实就是对原来整个training set的预测值,将他们拼凑起来,会形成一个10000行一列的矩阵,记为A1。而对于b1,b2,b3,b4,b5这部分数据,我们将各部分相加取平均值,得到一个2500行一列的矩阵,记为B1

以上就是stacking中一个模型的完整流程,stacking中同一层通常包含多个模型,假设还有Model2: LR,Model3:RF,Model4: GBDT,Model5:SVM,对于这四个模型,我们可以重复以上的步骤,在整个流程结束之后,我们可以得到新的A2,A3,A4,A5,B2,B3,B4,B5矩阵。

在此之后,我们把A1,A2,A3,A4,A5并列合并得到一个10000行五列的矩阵作为training data,B1,B2,B3,B4,B5并列合并得到一个2500行五列的矩阵作为testing data。让下一层的模型,基于他们进一步训练。

以上即为stacking的完整步骤!

四、集成方法投票分类器(Voting Classifiers)

sklearn.ensemble.VotingClassifier(estimators, voting=’hard’, weights=None, n_jobs=None, flatten_transform=None)

定义:对于一个训练集,有很多分类器,比如说Logistic、KNN、SVM等。对于一个样本,我们给出所有分类器的分类结果,然后利用这个结果对样本的分类进行预测 。
hard voting classifier :不考虑分类器的差别,比如说他们的准确性等,直接取投票数最多的类别,将其作为我们最后的对于该样本的分类结果,硬投票不能计算预测概率hard voting采用少数服从多数原则
soft voting classifier:利用所有分类器给出的各个类别的概率,最后利用各个类别的概率取平均进行预测,soft voting的准确率要略微高于hard voting,因为它考虑了每个模型的不同,当用soft voting进行集成时,会考虑概率,它不仅要看投给A多少票,B多少票,还要看到底有多大是我概率把样本分成A/B类,在使用时,就要求集合的每一个模型(逻辑回归,KNN,决策树,SVM)都能估计概率。
在很多情况下,投票分类器的精度会比集合里最好的分类器的精度还要高(对于大多数测试集),因为这种集成方法提高了模型的鲁棒性。当集成方法中的基学习器之间互相独立时,集成方法的效果会更好

from sklearn import datasets
from sklearn.metrics import accuracy_score
from sklearn.model_selection import train_test_split,cross_val_score
from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import BaggingRegressor
from sklearn.ensemble import RandomForestClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.svm import SVC
from sklearn.neighbors import KNeighborsClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.ensemble import VotingClassifier
from sklearn.ensemble import AdaBoostClassifier
from xgboost.sklearn import XGBClassifier
import numpy as np


alg1=DecisionTreeClassifier(min_samples_split=2, max_depth=30)
alg2=SVC(gamma=0.15, C=1,probability=True) #由于使用roc_auc_score作为评分标准,需将SVC中的probability参数设置为True
alg3=RandomForestClassifier(n_estimators=180,min_samples_split=4, max_depth=8)
alg4=AdaBoostClassifier(learning_rate=0.5,n_estimators= 100)
alg5=KNeighborsClassifier(n_neighbors= 9, leaf_size= 30)
alg6=XGBClassifier(n_estimators=140,max_depth=4,min_child_weight=5,random_state=29,n_jobs=-1,colsample_bytree=0.5, subsample= 0.6)
alg7=GradientBoostingClassifier(learning_rate=1.0, n_estimators=6, subsample=0.6)
# alg8=BaggingClassifier(base_estimator=SVC(gamma=0.15, C=1),n_estimators=500, max_samples=1, max_features=1.0, oob_score=True,random_state=0)
# alg9=BaggingClassifier(base_estimator=alg6,n_estimators=500, max_samples=1, max_features=1.0, oob_score=True,random_state=0)

iris=datasets.load_iris()
X_train,X_test,y_train,y_test=train_test_split(iris.data,iris.target,test_size=0.3,random_state=0)



model=VotingClassifier([('11',alg1),('22',alg2),('33',alg3),('44',alg4),('55',alg5),('66',alg6),('77',alg7)], voting='soft')

cross_score=cross_val_score(model,iris.data,iris.target,cv=3)

model.fit(X_train,y_train)
Y_pred=model.predict(X_test)
training_score=model.score(X_train,y_train)
testing_score=model.score(X_test,y_test)

print (cross_score,training_score,testing_score)
print (model.estimators_)
print (model.classes_)
#[0.98039216 0.94117647 0.97916667] 1.0 0.9777777777777777 soft
#[0.98039216 0.96078431 0.97916667] 0.9809523809523809 0.9777777777777777 hard

五、集成方法Blending

Blending与Stacking大致相同,只是Blending的主要区别在于训练集不是通过K-Fold的CV策略来获得预测值从而生成第二阶段模型的特征,而是建立一个Holdout集,例如说10%的训练数据,第二阶段的stacker模型就基于第一阶段模型对这10%训练数据的预测值进行拟合。说白了,就是把Stacking流程中的K-Fold CV 改成 HoldOut CV(随机将数据划分为两部分,一部分作为训练集,一部分作为测试集)。
Blending的优点在于:
1.比stacking简单(因为不用进行k次的交叉验证来获得stacker feature)
2.避开了一个信息泄露问题:generlizers和stacker使用了不一样的数据集
3.在团队建模过程中,不需要给队友分享自己的随机种子
而缺点在于:
1.使用了很少的数据(第二阶段的blender只使用training set10%的量)
2.blender可能会过拟合(其实大概率是第一点导致的)
3.stacking使用多次的CV会比较稳健

猜你喜欢

转载自blog.csdn.net/qq_39751437/article/details/86566864