集成学习综合教程(附Python代码)

 

本文约8000字,建议阅读10+分钟。

本文从基础集成技术讲起,随后介绍了高级的集成技术,最后特别介绍了一些流行的基于Bagging和Boosting的算法,帮助读者对集成学习建立一个整体印象。

 

介绍

 

当你想购买一辆新车时,你会走到第一家汽车商店就根据经销商的建议购买一辆车吗?这是不太可能的。

 

你可能会浏览一些人们发布评论并比较不同车型的门户网站,检查其功能和价格。你也可能会问你的朋友和同事们的意见。总之,你不会直接得出结论,还会参考其他人的意见做出决定。

640?wx_fmt=png

机器学习中的集成模型也是类似的思路。它们结合了多个模型的决策来提高整体性能。这可以通过各种方式实现,本文将会带你一起探索。

 

本文的目的是介绍集成学习的概念并理解使用这种技术的算法。为了巩固你对这个多元化主题的理解,我们将用真实问题的动手案例,配合Python来解释其中的高级算法。

 

注意:本文假定你对机器学习算法有基本的了解。我建议阅读这篇文章以熟悉这些概念。

 

文章链接:

https://www.analyticsvidhya.com/blog/2017/09/common-machine-learning-algorithms/

目录

 

  • 集成学习介绍

  • 基础集成技术

    • 最大投票(Max Voting)法

    • 平均(Averaging)法

    • 加权平均(Weighted Average)法

  • 高级集成技术

    • 堆叠(Stacking)

    • 混合(Blending)

    • Bagging

    •  提升(Boosting)

  • 基于Bagging和Boosting的算法

    • Bagging meta-estimator

    • 随机森林

    • AdaBoost

    • GBM

    • XGB

    • Light GBM

    • CatBoost

 

一、集成学习介绍

 

我们通过一个例子来理解集成学习的概念。假设你是一名电影导演,你依据一个非常重要且有趣的话题创作了一部短片。现在,你想在公开发布前获得影片的初步反馈(评级)。有哪些可行的方法呢?

 

A:可以请一位朋友为电影打分。

 

于是完全有可能出现这种结果:你所选择的人由于非常爱你,并且不希望给你这部糟糕的影片打1星评级来伤害你脆弱的小心脏。

 

B:另一种方法是让你的5位同事评价这部电影。

 

这个办法应该更好,可能会为电影提供更客观诚实的评分。但问题依然存在。这5个人可能不是电影主题方面的“专家”。当然,他们可能懂电影摄制,镜头或音效,但他们可能并不是黑色幽默的最佳评判者。

 

C:让50个人评价这部电影呢?

 

其中一些可以是你的朋友,可以是你的同事,甚至是完完全全的陌生人。

 

在这种情况下,回应将更加普遍化和多样化,因为他们拥有不同的技能。事实证明,与我们之前看到的情况相比,这是获得诚实评级的更好方法。

 

通过这些例子,你可以推断,与个人相比,不同群体的人可能会做出更好的决策。与单一模型相比,各种不同模型也是这个道理。机器学习中的多样化是通过称为集成学习(Ensemble learning)的技术实现的。

 

现在你已经掌握了集成学习的要旨,接下来让我们看看集成学习中的各种技术及其实现。

 

二、简单集成技术

 

这一节中,我们会看一些简单但是强大的技术,比如:

 

  • 最大投票法

  • 平均法

  • 加权平均法

 

2.1 最大投票法

 

最大投票方法通常用于分类问题。这种技术中使用多个模型来预测每个数据点。每个模型的预测都被视为一次“投票”。大多数模型得到的预测被用作最终预测结果。

 

例如,当你让5位同事评价你的电影时(最高5分); 我们假设其中三位将它评为4,而另外两位给它一个5。由于多数人评分为4,所以最终评分为4。你可以将此视为采用了所有预测的众数(mode)。

 

最大投票的结果有点像这样:

 

640?wx_fmt=jpeg

 

示例代码:

 

这里x_train由训练数据中的自变量组成,y_train是训练数据的目标变量。验证集是x_test(自变量)和y_test(目标变量)。

 

model1 = tree.DecisionTreeClassifier()

model2 = KNeighborsClassifier()

model3= LogisticRegression()

 

model1.fit(x_train,y_train)

model2.fit(x_train,y_train)

model3.fit(x_train,y_train)

 

pred1=model1.predict(x_test)

pred2=model2.predict(x_test)

pred3=model3.predict(x_test)

 

final_pred = np.array([])

for i in range(0,len(x_test)):

    final_pred =np.append(final_pred, mode([pred1[i], pred2[i], pred3[i]]))

 

或者,你也可以在sklearn中使用“VotingClassifier”模块,如下所示:

 

 

from sklearn.ensemble import VotingClassifier

 

model1 = LogisticRegression(random_state=1)

 

model2 = tree.DecisionTreeClassifier(random_state=1)

 

model = VotingClassifier(estimators=[('lr', model1), ('dt', model2)], voting='hard')

 

model.fit(x_train,y_train)

 

model.score(x_test,y_test)

 

2.2 平均法

 

类似于最大投票技术,这里对每个数据点的多次预测进行平均。在这种方法中,我们从所有模型中取平均值作为最终预测。平均法可用于在回归问题中进行预测或在计算分类问题的概率时使用。

 

例如,在下面的情况中,平均法将取所有值的平均值。

 

即(5 + 4 + 5 + 4 + 4)/ 5 = 4.4

 

640?wx_fmt=jpeg

 

示例代码:

 

 

model1 = tree.DecisionTreeClassifier()

 

model2 = KNeighborsClassifier()

 

model3= LogisticRegression()

 

 

 

model1.fit(x_train,y_train)

 

model2.fit(x_train,y_train)

 

model3.fit(x_train,y_train)

 

 

 

pred1=model1.predict_proba(x_test)

 

pred2=model2.predict_proba(x_test)

 

pred3=model3.predict_proba(x_test)

 

 

 

finalpred=(pred1+pred2+pred3)/3

 

2.3 加权平均法

 

这是平均法的扩展。为所有模型分配不同的权重,定义每个模型的预测重要性。例如,如果你的两个同事是评论员,而其他人在这方面没有任何经验,那么与其他人相比,这两个朋友的答案就更加重要。

 

计算结果为[(5 * 0.23)+(4 * 0.23)+(5 * 0.18)+(4 * 0.18)+(4 * 0.18)] = 4.41。

 

640?wx_fmt=png

示例代码:

 

 

model1 = tree.DecisionTreeClassifier()

 

model2 = KNeighborsClassifier()

 

model3= LogisticRegression()

 

 

 

model1.fit(x_train,y_train)

 

model2.fit(x_train,y_train)

 

model3.fit(x_train,y_train)

 

 

 

pred1=model1.predict_proba(x_test)

 

pred2=model2.predict_proba(x_test)

 

pred3=model3.predict_proba(x_test)

 

 

 

finalpred=(pred1*0.3+pred2*0.3+pred3*0.4)

 

三、高级集成技术

 

我们已经介绍了基础的集成技术,让我们继续了解高级的技术。

 

3.1 堆叠(Stacking)

 

Stacking和Blending是两种集成分类器的相似方法,在实际中应用Stacking较多,此处以Stacking进行讲解。

Stacking是一种分层模型集成框架。以两层为例,第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为特征加入训练集进行再训练,从而得到完整的Stacking模型。

Stacking的过程有一张图非常经典,如下:

图5的上半部分是用一个基础模型进行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的完整步骤!为了方便理解,这里借用了该文章的插图。

有一篇文章对stacking讲的挺透彻的:https://www.aboutyun.com/thread-27205-1-1.html

Blending与Stacking的区别
Blending与Stacking大致相同,只是Blending的主要区别在于训练集不是通过K-Fold的CV策略来获得预测值从而生成第二阶段模型的特征,而是建立一个Holdout集,例如说10%的训练数据,第二阶段的stacker模型就基于第一阶段模型对这10%训练数据的预测值进行拟合。说白了,就是把Stacking流程中的K-Fold CV 改成 HoldOut CV。

Blending的优点在于:

比stacking简单(因为不用进行k次的交叉验证来获得stacker feature)
避开了一个信息泄露问题:generlizers和stacker使用了不一样的数据集
在团队建模过程中,不需要给队友分享自己的随机种子
而缺点在于:

使用了很少的数据(第二阶段的blender只使用training set10%的量)
blender可能会过拟合(其实大概率是第一点导致的)
stacking使用多次的CV会比较稳健
对于实践中的结果而言,stacking和blending的效果是差不多的,所以使用哪种方法都没什么所谓,完全取决于个人爱好。

代码:

from __future__ import division
import numpy as np
from sklearn.cross_validation import train_test_split 
from sklearn.datasets import load_breast_cancer
from sklearn.cross_validation import StratifiedKFold
from sklearn.ensemble import RandomForestClassifier, ExtraTreesClassifier
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
 
if __name__ == '__main__':
 
    np.random.seed(0)  # seed to shuffle the train set
    n_folds = 10
    verbose = True
    shuffle = False
    data=load_breast_cancer()
    X=data.data
    y=data.target
    #划分数据集
    X_train,X_test,y_train,y_test=train_test_split(X,y,random_state=0,test_size=0.2)
    
    if shuffle:
        idx = np.random.permutation(y_train.size)
        X_train = X_train[idx]
        y_train = y_train[idx]
 
    skf = list(StratifiedKFold(y_train, n_folds))
 
    clfs = [RandomForestClassifier(n_estimators=100, n_jobs=-1, criterion='gini'),
            RandomForestClassifier(n_estimators=100, n_jobs=-1, criterion='entropy'),
            ExtraTreesClassifier(n_estimators=100, n_jobs=-1, criterion='gini'),
            ExtraTreesClassifier(n_estimators=100, n_jobs=-1, criterion='entropy'),
            GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=100)]
 
    print( "Creating train and test sets for stacking.")
 
    dataset_blend_train = np.zeros((X_train.shape[0], len(clfs)))
    dataset_blend_test = np.zeros((X_test.shape[0], len(clfs)))
 
    for j, clf in enumerate(clfs):
        print (j, clf)
        dataset_blend_test_j = np.zeros((X_test.shape[0], len(skf)))
        for i, (train, test) in enumerate(skf):
            print("Fold", i)
            X_train_b = X_train[train]
            y_train_b = y_train[train]
            X_test_b = X_train[test]
            y_test_b = y_train[test]
            clf.fit(X_train_b, y_train_b)
            y_submission = clf.predict_proba(X_test_b)[:, 1]
            dataset_blend_train[test, j] = y_submission
            dataset_blend_test_j[:, i] = clf.predict_proba(X_test)[:, 1]
        dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
 
    print( "Stacking.")
    clf = LogisticRegression()
    clf.fit(dataset_blend_train, y_train)
    print("Stacking Accuracy %0.6f:"%accuracy_score(y_test,clf.predict(dataset_blend_test)))
    n=1
    for model in clfs:
        model.fit(X_train,y_train)
        y_test_pred = model.predict(X_test)
        print("模型%d,Accuracy %0.6f:"%(n,accuracy_score(y_test,y_test_pred)))
        n=n+1


**********************************************

堆叠是一种集成学习技术,它使用多个模型(例如决策树,knn或svm)的预测来构建新模型。该新模型用于对测试集进行预测。以下是简单堆叠集成法的逐步解释:

 

第一步:把训练集分成10份

 

640?wx_fmt=jpeg

 

第二步:基础模型(假设是决策树)在其中9份上拟合,并对第10份进行预测。

第三步:对训练集上的每一份如此做一遍。

 

640?wx_fmt=jpeg

 

第四步:然后将基础模型(此处是决策树)拟合到整个训练集上。

第五步:使用此模型,在测试集上进行预测。

 

640?wx_fmt=jpeg

 

第六步:对另一个基本模型(比如knn)重复步骤2到4,产生对训练集和测试集的另一组预测。

 

640?wx_fmt=jpeg

 

第七步:训练集预测被用作构建新模型的特征。

 

第八步:该新模型用于对测试预测集(test prediction set,上图的右下角)进行最终预测。

 

640?wx_fmt=jpeg

示例代码:

 

我们首先定义一个函数来对n折的训练集和测试集进行预测。此函数返回每个模型对训练集和测试集的预测。

 

 

def Stacking(model,train,y,test,n_fold):

 

   folds=StratifiedKFold(n_splits=n_fold,random_state=1)

 

   test_pred=np.empty((test.shape[0],1),float)

 

   train_pred=np.empty((0,1),float)

 

   for train_indices,val_indices in folds.split(train,y.values):

 

      x_train,x_val=train.iloc[train_indices],train.iloc[val_indices]

 

      y_train,y_val=y.iloc[train_indices],y.iloc[val_indices]

 

 

 

      model.fit(X=x_train,y=y_train)

 

      train_pred=np.append(train_pred,model.predict(x_val))

 

      test_pred=np.append(test_pred,model.predict(test))

 

    return test_pred.reshape(-1,1),train_pred

 

现在我们将创建两个基本模型:决策树和knn。

 

 

model1 = tree.DecisionTreeClassifier(random_state=1)

 

 

 

test_pred1 ,train_pred1=Stacking(model=model1,n_fold=10, train=x_train,test=x_test,y=y_train)

 

 

 

train_pred1=pd.DataFrame(train_pred1)

 

test_pred1=pd.DataFrame(test_pred1)

 

 

model2 = KNeighborsClassifier()

 

 

 

test_pred2 ,train_pred2=Stacking(model=model2,n_fold=10,train=x_train,test=x_test,y=y_train)

 

 

 

train_pred2=pd.DataFrame(train_pred2)

 

test_pred2=pd.DataFrame(test_pred2)

 

创建第三个模型,逻辑回归,在决策树和knn模型的预测之上。

 

 

df = pd.concat([train_pred1, train_pred2], axis=1)

 

df_test = pd.concat([test_pred1, test_pred2], axis=1)

 

 

 

model = LogisticRegression(random_state=1)

 

model.fit(df,y_train)

 

model.score(df_test, y_test)

 

为了简化上面的解释,我们创建的堆叠模型只有两层。决策树和knn模型建立在零级,而逻辑回归模型建立在第一级。其实可以随意的在堆叠模型中创建多个层次。

 

3.2 混合(Blending

 

混合遵循与堆叠相同的方法,但仅使用来自训练集的一个留出(holdout)/验证集来进行预测。换句话说,与堆叠不同,预测仅在留出集上进行。留出集和预测用于构建在测试集上运行的模型。以下是混合过程的详细说明:

 

第一步:原始训练数据被分为训练集合验证集。

 

640?wx_fmt=jpeg

 

第二步:在训练集上拟合模型。

第三步:在验证集和测试集上进行预测。

 

640?wx_fmt=jpeg

 

第四步:验证集及其预测用作构建新模型的特征。

第五步:该新模型用于对测试集和元特征(meta-features)进行最终预测。

 

示例代码:

 

我们将在训练集上建立两个模型,决策树和knn,以便对验证集进行预测。

 

 

model1 = tree.DecisionTreeClassifier()

 

model1.fit(x_train, y_train)

 

val_pred1=model1.predict(x_val)

 

test_pred1=model1.predict(x_test)

 

val_pred1=pd.DataFrame(val_pred1)

 

test_pred1=pd.DataFrame(test_pred1)

 

 

 

model2 = KNeighborsClassifier()

 

model2.fit(x_train,y_train)

 

val_pred2=model2.predict(x_val)

 

test_pred2=model2.predict(x_test)

 

val_pred2=pd.DataFrame(val_pred2)

 

test_pred2=pd.DataFrame(test_pred2)

 

结合元特征和验证集,构建逻辑回归模型以对测试集进行预测。

 

 

df_val=pd.concat([x_val, val_pred1,val_pred2],axis=1)

 

df_test=pd.concat([x_test, test_pred1,test_pred2],axis=1)

 

 

 

model = LogisticRegression()

 

model.fit(df_val,y_val)

 

model.score(df_test,y_test)

 

 

针对Stacking和Blending,数据科学竞赛工具集heamy中已经打包实现,可以直接调用。通过pip install heamy进行安装。具体使用说明参考文档:https://heamy.readthedocs.io/en/latest/

 

Stacking

from heamy.dataset import Dataset
from heamy.estimator import Regressor, Classifier
from heamy.pipeline import ModelsPipeline
from sklearn import cross_validation
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
#加载数据集
from sklearn.datasets import load_boston
data = load_boston()
X, y = data['data'], data['target']
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.1, random_state=111)
#创建数据集
dataset = Dataset(X_train,y_train,X_test)
#创建RF模型和LR模型
model_rf = Regressor(dataset=dataset, estimator=RandomForestRegressor, parameters={'n_estimators': 50},name='rf')
model_lr = Regressor(dataset=dataset, estimator=LinearRegression, parameters={'normalize': True},name='lr')
# Stack两个模型
# Returns new dataset with out-of-fold predictions
pipeline = ModelsPipeline(model_rf,model_lr)
stack_ds = pipeline.stack(k=10,seed=111)
#第二层使用lr模型stack
stacker = Regressor(dataset=stack_ds, estimator=LinearRegression)
results = stacker.predict()
# 使用10折交叉验证结果
results10 = stacker.validate(k=10,scorer=mean_absolute_error)

Blending

from heamy.dataset import Dataset
from heamy.estimator import Regressor, Classifier
from heamy.pipeline import ModelsPipeline
from sklearn import cross_validation
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
#加载数据集
from sklearn.datasets import load_boston
data = load_boston()
X, y = data['data'], data['target']
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.1, random_state=111)
#创建数据集
dataset = Dataset(X_train,y_train,X_test)
#创建RF模型和LR模型
model_rf = Regressor(dataset=dataset, estimator=RandomForestRegressor, parameters={'n_estimators': 50},name='rf')
model_lr = Regressor(dataset=dataset, estimator=LinearRegression, parameters={'normalize': True},name='lr')
# Blending两个模型
# Returns new dataset with out-of-fold predictions
pipeline = ModelsPipeline(model_rf,model_lr)
stack_ds = pipeline.blend(proportion=0.2,seed=111)
#第二层使用lr模型stack
stacker = Regressor(dataset=stack_ds, estimator=LinearRegression)
results = stacker.predict()
# 使用10折交叉验证结果
results10 = stacker.validate(k=10,scorer=mean_absolute_error)


加权平均  

from heamy.dataset import Dataset
from heamy.estimator import Regressor, Classifier
from heamy.pipeline import ModelsPipeline
from sklearn import cross_validation
from sklearn.ensemble import RandomForestRegressor
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_absolute_error
from sklearn.neighbors import KNeighborsRegressor
from sklearn.datasets import load_boston
data = load_boston()
X, y = data['data'], data['target']
X_train, X_test, y_train, y_test = cross_validation.train_test_split(X, y, test_size=0.1, random_state=111)
#创建数据集
dataset = Dataset(X_train,y_train,X_test)
 
model_rf = Regressor(dataset=dataset, estimator=RandomForestRegressor, parameters={'n_estimators': 151},name='rf')
model_lr = Regressor(dataset=dataset, estimator=LinearRegression, parameters={'normalize': True},name='lr')
model_knn = Regressor(dataset=dataset, estimator=KNeighborsRegressor, parameters={'n_neighbors': 15},name='knn')
 
pipeline = ModelsPipeline(model_rf,model_lr,model_knn)
 
weights = pipeline.find_weights(mean_absolute_error)
result = pipeline.weight(weights)

3.3 Bagging

集成学习中的个体学习器应尽可能的相互独立,虽然独立在现实任务中无法做到,但可以设法使基学习器尽可能具有较大的差异。给定一个训练数据集,一种可能的做法是对训练样本进行采样,产生出若干个不同的子集,再从每个数据子集中训练出一个基学习器,这样由于训练数据的不同,我们获得的基学习器可望具有较大的差异,而然,为了获得好的集成,我们同时还希望个体学习器不能太差。如果采样出的每个子集都完全不同,则每个基学习器只用到了一小部分训练数据,甚至不足以进行有效学习,为了解决这个问题,我们考虑使用相互有交叠的采样子集。

给定包含 m 个样本的数据集,我们先随机取出一个样本放入采样集中,再把该样本放回初始数据集,使得下次采样时该样本仍有可能被选中,经过 m 次随机采样操作,我们得到含 m 个样本的采样集,初始训练集中有的样本在采样集里多次出现,有的则从未出现。

Bagging背后的想法是结合多个模型的结果(例如,所有决策树)来获得泛化的结果。这有一个问题:如果在同样一组数据上创建所有模型并将其组合起来,它会有用吗?这些模型极大可能会得到相同的结果,因为它们获得的输入相同。那我们该如何解决这个问题呢?其中一种技术是自举(bootstrapping)。

 

Bootstrapping是一种采样技术,我们有放回的从原始数据集上创建观察子集,子集的大小与原始集的大小相同。

 

Bagging(或Bootstrap Aggregating)技术使用这些子集(包)来获得分布的完整概念(完备集)。为bagging创建的子集的大小也可能小于原始集。

Bagging的策略如下:

1.从样本集中重采样(有重复的)选出n个样本
2.在所有属性上,对这n个样本建立分类器(ID3、C4.5、CART、SVM、Logistic回归等)
3.重复1、2…… m 次,即获得了 m 个分类器
4.将数据放在这m个分类器上,最后根据这 m 个分类器的投票结果,决定数据属于哪一类

Bagging采用的重采样,即为评估方法中的自助法(bootstrapping)。可以做一个简单的估计,样本在m次采样中始终不被采到的概率是

取极限得到: 

即通过自主法采样,初始数据集中有约36.8%的样本未出现在采样数据集中,将这些未参与模型训练的数据称为袋外数据(包外估计,out-of-bag estimate)。
 

 

 

3.4 Boosting

Boosting是一族可以将弱学习器提升为强学习器的算法,这族算法的工作机制类似:①先从初始训练集训练出一个基学习器;②再根据基学习器的表现对训练样本分布进行调整,使得先前基学习器做错的训练样本在后续受到更多的关注;③然后基于调整后的样本分步来训练下一个基学习器。如此重复,直到基学习器的数目达到事先制定的T值,最终将这T个基学习器进行加权结合。Boosting族的最著名的代表是AdaBoost。

在我们进一步讨论之前,这里有另一个问题:如果第一个模型错误地预测了某一个数据点,然后接下来的模型(可能是所有模型),将预测组合起来会提供更好的结果吗?Boosting就是来处理这种情况的。

 

Boosting是一个顺序过程,每个后续模型都会尝试纠正先前模型的错误。后续的模型依赖于之前的模型。接下来一起看看boosting的工作方式:

 

第一步:从原始数据集创建一个子集。

第二步:最初,所有数据点都具有相同的权重。

第三步:在此子集上创建基础模型。

第四步:该模型用于对整个数据集进行预测。

 

640?wx_fmt=jpeg

 

第五步:使用实际值和预测值计算误差。

第六步:预测错误的点获得更高的权重。(这里,三个错误分类的蓝色加号点将被赋予更高的权重)

第七步:创建另一个模型并对数据集进行预测(此模型尝试更正先前模型中的错误)。

 

640?wx_fmt=png

 

第八步:类似地,创建多个模型,每个模型校正先前模型的错误。

第九步:最终模型(强学习器)是所有模型(弱学习器)的加权平均值。

 

640?wx_fmt=png

 

因此,boosting算法结合了许多弱学习器来形成一个强学习器。单个模型在整个数据集上表现不佳,但它们在数据集的某些部分上表现很好。因此,每个模型实际上提升了集成的整体性能。

 

 640?wx_fmt=jpeg

 

四、基于Bagging和Boosting的算法

 

Bagging和Boosting是机器学习中最常用的两种技术。在本节中,我们将详细介绍它们。以下是我们将关注的算法:

务必记住,bagging和boosting针对的都是同质学习器(即各个模型都是一种类型的方法,比如30个学习器都是决策树,,这从代码里也看得出来。

Bagging 算法:

  • Bagging meta-estimator

  • 随机森林

 

Boosting算法:

  • AdaBoost

  • GBM

  • XGBM

  • Light GBM

  • CatBoost

 

对于本节中讨论的所有算法,我们将遵循以下顺序:

  • 算法介绍

  • 示例代码

  • 参数

 

本文中,我使用了贷款预测问题。你可以从此处下载数据集。请注意,对于每种算法,某些代码(读取数据,划分训练测试集等)将是相同的。为了避免重复,我在下面编写了相同的代码,并且只对算法相关的代码进行进一步讨论。

 

 

#importing important packages

 

import pandas as pd

 

import numpy as np

 

 

 

#reading the dataset

 

df=pd.read_csv("/home/user/Desktop/train.csv")

 

 

 

#filling missing values

 

df['Gender'].fillna('Male', inplace=True)

 

同理,对所有列进行值填充。本文只考虑所讨论的主题,已跳过EDA,缺失值和异常值处理等步骤。要了解这些主题,可以阅读此文:Ultimate guide for Data Explorationin Python using NumPy, Matplotlib and Pandas.

 

 

#split dataset into train and test

 

 

 

from sklearn.model_selection import train_test_split

 

train, test = train_test_split(df, test_size=0.3, random_state=0)

 

 

 

x_train=train.drop('Loan_Status',axis=1)

 

y_train=train['Loan_Status']

 

 

 

x_test=test.drop('Loan_Status',axis=1)

 

y_test=test['Loan_Status']

 

 

 

#create dummies

 

x_train=pd.get_dummies(x_train)

 

x_test=pd.get_dummies(x_test)

 

让我们来探索bagging和boosting算法。

 

4.1 Bagging meta-estimator

 

Bagging meta-estimator是一种集成算法,可用于分类(BaggingClassifier)和回归(BaggingRegressor)问题。它采用典型的bagging技术进行预测。以下是Bagging meta-estimator算法的步骤:

 

第一步:从原始数据集(Bootstrapping)创建随机子集。

第二步:数据集的子集包括所有特征。

第三步用户指定的基础估计器在这些较小的集合上拟合。

第四步:将每个模型的预测结合起来得到最终结果。

 

示例代码:

 

 

from sklearn.ensemble import BaggingClassifier

 

from sklearn import tree

 

model = BaggingClassifier(tree.DecisionTreeClassifier(random_state=1))

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

0.75135135135135134

 

回归问题示例代码:

 

 

from sklearn.ensemble import BaggingRegressor

 

model = BaggingRegressor(tree.DecisionTreeRegressor(random_state=1))

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

算法中用到的参数:

 

  • base_estimator

    • 定义了在随机子集上拟合所用的基础估计器

    • 没有指明时,默认使用决策树

  • n_estimators

    • 创建的基础估计器数量

    • 要小心微调这个参数,因为数字越大运行时间越长,相反太小的数字可能无法提供最优结果

  • max_samples

    • 该参数控制子集的大小

    • 它是训练每个基础估计器的最大样本数量

  • max_features

    • 控制从数据集中提取多少个特征

    • 它是训练每个基础估计器的最大特征数量

  • n_jobs

    • 同时运行的job数量

    • 将这个值设为你系统的CPU核数

    • 如果设为-1,这个值会被设为你系统的CPU核数

  • random_state

    • 定义了随机分割的方法。当两个模型的random_state值一样时,它们的随机选择也一样

    • 如果你想对比不同的模型,这个参数很有用

 

4.2 随机森林

 

随机森林是另一种遵循bagging技术的集成机器学习算法。它是bagging-estimator算法的扩展。随机森林中的基础估计器是决策树。与bagging meta-estimator不同,随机森林随机选择一组特征,这些特征用于决定决策树的每个节点处的最佳分割。

 

随机森林的具体步骤如下:

 

第一步:从原始数据集(Bootstrapping)创建随机子集。

第二步:在决策树中的每个节点处,仅考虑一组随机特征来决定最佳分割。

第三步:在每个子集上拟合决策树模型。

第四步:通过对所有决策树的预测求平均来计算最终预测。

 

注意:随机林中的决策树可以构建在数据和特征的子集上。特别地,sklearn中的随机森林使用所有特征作为候选,并且候选特征的随机子集用于在每个节点处分裂。

 

总而言之,随机森林随机选择数据点和特征,并构建多个树(森林)。

 

示例代码:

 

 

from sklearn.ensemble import RandomForestClassifier

 

model= RandomForestClassifier(random_state=1)

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

0.77297297297297296

 

你可以通过在随机林中使用model.feature_importances_来查看特征重要性。

 

 

for i, j in sorted(zip(x_train.columns, model.feature_importances_)):

 

    print(i, j)

 

结果如下:

 

 

ApplicantIncome 0.180924483743

 

CoapplicantIncome 0.135979758733

 

Credit_History 0.186436670523

 

.

 

.

 

.

 

Property_Area_Urban 0.0167025290557

 

Self_Employed_No 0.0165385567137

 

Self_Employed_Yes 0.0134763695267

回归问题示例代码:

 

from sklearn.ensemble import RandomForestRegressor

 

model= RandomForestRegressor()

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

参数:

 

  • n_estimators

    • 定义随机森林中要创建的决策树数量

    • 通常,越高的值会让预测更强大更稳定,但是过高的值会让训练时间很长

  • criterion

    • 定义了分割用的函数

    • 该函数用来衡量使用每个特征分割的质量从而选择最佳分割

  • max_features

    • 定义了每个决策树中可用于分割的最大特征数量

    • 增加最大特征数通常可以改善性能,但是一个非常高的值会减少各个树之间的差异性

  • max_depth

    • 随机森林有多个决策树,此参数定义树的最大深度

  • min_samples_split

    • 用于在尝试拆分之前定义叶节点中所需的最小样本数

    • 如果样本数小于所需数量,则不分割节点

  • min_samples_leaf

    • 定义了叶子节点所需的最小样本数

    • 较小的叶片尺寸使得模型更容易捕获训练数据中的噪声

  • max_leaf_nodes

    • 此参数指定每个树的最大叶子节点数

    • 当叶节点的数量变得等于最大叶节点时,树停止分裂

  • n_jobs

    • 这表示并行运行的作业数

    • 如果要在系统中的所有核心上运行,请将值设置为-1

  • random_state

    • 此参数用于定义随机选择

    • 它用于各种模型之间的比较

 

下面是决策树以及Bagging和随机森林在UCI的Breast cancer数据集上的表现。 

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import BaggingClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
 
#读入乳腺癌数据集
data=load_breast_cancer()
x=pd.DataFrame(data.data)
y=data.target
#划分数据集
X_train,X_test,y_train,y_test=train_test_split(x,y,random_state=0,test_size=0.3)
 
# 度量单个决策树的准确性
tree = DecisionTreeClassifier(criterion='entropy', 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))
#Decision tree train/test accuracies 1.000/0.942
 
# 度量bagging分类器的准确性
# 生成500个决策树,详细的参数建议参考官方文档
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('Bagging train/test accuracies %.3f/%.3f' % (bag_train, bag_test))
#Bagging train/test accuracies 1.000/0.959
 
#随机森林,bagging思想
rf = RandomForestClassifier(n_estimators=1000,  max_features='sqrt', max_depth=None, min_samples_split=2, bootstrap=True, n_jobs=1, random_state=1)
# 度量随机森林的准确性
rf = rf.fit(X_train, y_train)
y_train_pred = rf.predict(X_train)
y_test_pred = rf.predict(X_test)
tree_train = accuracy_score(y_train, y_train_pred)
tree_test = accuracy_score(y_test, y_test_pred)
print('Random Forest train/test accuracies %.3f/%.3f' % (tree_train, tree_test)) 
#RandomFores train/test accuracies 1.000/0.971

其输出结果是

Decision tree train/test accuracies 1.000/0.942
Bagging train/test accuracies 1.000/0.959
Random Forest train/test accuracies 1.000/0.971

 

4.3 AdaBoost

 

自适应增强或AdaBoost是最简单的boosting算法之一。通常用决策树来建模。创建多个顺序模型,每个模型都校正上一个模型的错误。AdaBoost为错误预测的观测值分配权重,后续模型来正确预测这些值。

 

以下是执行AdaBoost算法的步骤:

 

第一步:最初,数据集中的所有观察值都具有相同的权重。

第二步:在数据子集上建立一个模型。

第三步:使用此模型,可以对整个数据集进行预测。

第四步:通过比较预测值和实际值来计算误差。

第五步:在创建下一个模型时,会给预测错误的数据点赋予更高的权重。

第六步:可以使用误差值确定权重。例如,误差越大,分配给观察值的权重越大。

第七步:重复该过程直到误差函数没有改变,或达到估计器数量的最大限制。

换句话说:

Adaboost算法可以简述为三个步骤:

初始化训练数据的权值分布D1。假设有N个训练样本数据,则每一个训练样本最开始时,都被赋予相同的权值:w1=1/N。
训练弱分类器hi。具体训练过程中是:如果某个训练样本点,被弱分类器hi准确地分类,那么在构造下一个训练集中,它对应的权值要减小;相反,如果某个训练样本点被错误分类,那么它的权值就应该增大。权值更新过的样本集被用于训练下一个分类器,整个训练过程如此迭代地进行下去。
将各个训练得到的弱分类器组合成一个强分类器。各个弱分类器的训练过程结束后,加大分类误差率小的弱分类器的权重,使其在最终的分类函数中起着较大的决定作用,而降低分类误差率大的弱分类器的权重,使其在最终的分类函数中起着较小的决定作用。
  换而言之,误差率低的弱分类器在最终分类器中占的权重较大,否则较小。
 

示例代码:

 

 

from sklearn.ensemble import AdaBoostClassifier

 

model = AdaBoostClassifier(random_state=1)

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

0.81081081081081086

 

回归问题示例代码:

 

 

from sklearn.ensemble import AdaBoostRegressor

 

model = AdaBoostRegressor()

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

参数:

 

  • base_estimators

    • 它用于指定基础估计器的类型,即用作基础学习器的机器学习算法

  • n_estimators

    • 它定义了基础估计器的数量

    • 默认值为10,但可以设为较高的值以获得更好的性能

  • learning_rate

    • 此参数控制估计器在最终组合中的贡献

    • 在learning_rate和n_estimators之间需要进行权衡

  • max_depth

    • 定义单个估计器的最大深度

    • 调整此参数以获得最佳性能

  • n_jobs

    • 指定允许使用的处理器数

    • 将值设为-1,可以使用允许的最大处理器数量

  • random_state

    • 用于指定随机数据拆分的整数值

    • 如果给出相同的参数和训练数据,random_state的确定值将始终产生相同的结果

 

4.4 Gradient Boosting(梯度提升GBM)

 

Gradient Boosting或GBM是另一种集成机器学习算法,适用于回归和分类问题。GBM使用boosting技术,结合了许多弱学习器,以形成一个强大的学习器。回归树用作基础学习器,每个后续的树都是基于前一棵树计算的错误构建的。

GBDT也是集成学习Boosting家族的成员,但是却和传统的Adaboost有很大的不同。在Adaboost中,我们是利用前一轮迭代弱学习器的误差率来更新训练集的权重,这样一轮轮的迭代下去。GBDT也是迭代,使用了前向分布算法,但是弱学习器限定了只能使用CART回归树模型,同时迭代思路和Adaboost也有所不同。

GBDT的思想可以用一个通俗的例子解释,假如有个人30岁,我们首先用20岁去拟合,发现损失有10岁,这时我们用6岁去拟合剩下的损失,发现差距还有4岁,第三轮我们用3岁拟合剩下的差距,差距就只有一岁了。如果我们的迭代轮数还没有完,可以继续迭代下面,每一轮迭代,拟合的岁数误差都会减小。
 

我们将使用一个简单的例子来理解GBM算法。我们会使用以下数据预测一群人的年龄:

 

640?wx_fmt=jpeg

 

第一步:假设平均年龄是数据集中所有观测值的预测值。

第二步:使用该平均预测值和年龄的实际值来计算误差:

 

640?wx_fmt=png

第三步:使用上面计算的误差作为目标变量创建树模型。我们的目标是找到最佳分割以最小化误差。

第四步:该模型的预测与预测1相结合:

 

640?wx_fmt=jpeguploading.gif转存失败重新上传取消640?wx_fmt=jpeg

 

第五步:上面计算的这个值是新的预测。

第六步:使用此预测值和实际值计算新误差:

 

640?wx_fmt=png

 

第七步:重复步骤2到6,直到最大迭代次数(或误差函数不再改变)

 

示例代码:

 

 

from sklearn.ensemble import GradientBoostingClassifier

 

model= GradientBoostingClassifier(learning_rate=0.01,random_state=1)

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

0.81621621621621621

 

回归问题示例代码:

 

 

from sklearn.ensemble import GradientBoostingRegressor

 

model= GradientBoostingRegressor()

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

参数:

 

  • min_samples_split

    • 定义考虑被拆分的节点中所需的最小样本数(或观察值数)

    • 用于控制过配合。较高的值会阻止模型学习关系,这种关系可能对为一棵树选择的特定样本高度特定

  • min_samples_leaf

    • 定义终端或叶节点中所需的最小样本数

    • 一般来说,应该为不平衡的分类问题选择较低的值,因为少数群体占大多数的地区将非常小

  • min_weight_fraction_leaf

    • 与min_samples_leaf类似,但定义为观察总数的一个比例而不是整数

  • max_depth

    • 树的最大深度。

    • 用于控制过拟合,因为更高的深度将让模型学习到非常特定于某个样本的关系

    • 应该使用CV进行调整

  • max_leaf_nodes

    • 树中终端节点或叶子的最大数量

    • 可以用于代替max_depth。由于创建了二叉树,因此深度'n'将产生最多2 ^ n个叶子

    • 如果它被定义,则GBM会忽略max_depth

  • max_features

    • 搜索最佳拆分时要考虑的特征数量。这些特征将被随机选择。

    • 作为一个经验法则,特征总数的平方根效果很好,但我们可以尝试直到特征总数的30-40%。

    • 较高的值可能导致过度拟合,但通常取决于具体情况。

 

4.5 XGBoost

 

XGBoost(extreme Gradient Boosting)是梯度提升算法的高级实现。实践证明,XGBoost是一种高效的ML算法,广泛应用于机器学习竞赛和黑客马拉松。 XGBoost具有很高的预测能力,几乎比其他梯度提升技术快10倍。它还包括各种正规化,可减少过拟合并提高整体性能。因此,它也被称为“正则化提升”技术。

相对于传统的GBDT,XGBoost使用了二阶信息,可以更快的在训练集上收敛。这可是kaggle等各类比赛的大杀器!

由于“随机森林族”本身具备过拟合的优势,因此XGBoost仍然一定程度的具有该特性。

XGBoost的实现中使用了并行/多核计算,因此训练速度快;同时他的原生语言为C/C++,这是它速度快的原因。
 

让我们看看XGBoost为何比其他技术更好:

 

  • 正则化:

    • 标准GBM实现没有像XGBoost那样的正则化

    • 因此,XGBoost还有助于减少过拟合

  • 并行处理:

    • XGBoost实现并行处理,并且比GBM更快

    • XGBoost还支持Hadoop上的实现

  • 高灵活性:

    • XGBoost允许用户自定义优化目标和评估标准,为模型添加全新维度

  • 处理缺失值:

    • XGBoost有一个内置的例程来处理缺失值

  • 树剪枝:

    • XGBoost先进行分割,直到指定的max_depth,然后开始向后修剪树并删除没有正向增益的分割

  • 内置交叉验证:

    • XGBoost允许用户在提升过程的每次迭代中运行交叉验证,因此很容易在一次运行中获得精确的最佳提升迭代次数

 

示例代码:

 

由于XGBoost会自行处理缺失值,因此你不必再处理。你可以跳过上述代码中缺失值插补的步骤。如下展示了如何应用xgboost:

 

 

import xgboost as xgb

 

model=xgb.XGBClassifier(random_state=1,learning_rate=0.01)

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

0.82702702702702702

 

回归问题示例代码:

 

 

import xgboost as xgb

 

model=xgb.XGBRegressor()

 

model.fit(x_train, y_train)

 

model.score(x_test,y_test)

 

参数:

 

  • nthread

    • 这用于并行处理,应输入系统中的核心数

    • 如果你希望在所有核心上运行,请不要输入此值。该算法将自动检测

  • eta

    • 类似于GBM中的学习率

    • 通过缩小每一步的权重,使模型更加健壮

  • min_child_weight

    • 定义子节点中所有观察值的最小权重和

    • 用于控制过拟合。较高的值会阻止模型学习关系,这种关系可能高度特定于为某个树所选的具体样本

  • max_depth

    • 它用于定义最大深度

    • 更高的深度将让模型学习到非常特定于某个样本的关系

  • max_leaf_nodes

    • 树中终端节点或叶子的最大数量

    • 可以用来代替max_depth。由于创建了二叉树,因此深度'n'将产生最多2 ^ n个叶子

    • 如果已定义,则GBM将忽略max_depth

  • gamma

    • 仅当产生的分割能给出损失函数的正向减少时,才分割节点。Gamma指定进行分割所需的最小损失减少量。

    • 使算法保守。值可能会根据损失函数而有所不同,因此应进行调整

  • subsample

    • 与GBM的子样本相同。表示用于每棵树随机采样的观察值的比例。

    • 较低的值使算法更加保守并防止过拟合,但是太小的值可能导致欠拟合。

  • colsample_bytree

    • 它类似于GBM中的max_features

    • 表示要为每个树随机采样的列的比例

 

4.6 Light GBM

 

在讨论Light GBM如何工作之前,先理解为什么在我们有如此多其他算法时(例如我们上面看到的算法)我们还需要这个算法。当数据集非常大时,Light GBM会击败所有其他算法。与其他算法相比,Light GBM在较大的数据集上运行所需的时间较短。

 

LightGBM是一个梯度提升框架,它使用基于树的算法并遵循逐叶子的方式(leaf-wise),而其他算法以逐层级(level-wise)模式工作。下图帮助你更好地理解二者差异:

640?wx_fmt=png

 

640?wx_fmt=jpeg

 

逐叶子方式可能在较小的数据集上导致过拟合,但可以通过使用'max_depth'参数来避免这种情况。你可以在本文中阅读有关Light GBM及其与XGB比较的更多信息。

 

示例代码:

 

 

import lightgbm as lgb

 

train_data=lgb.Dataset(x_train,label=y_train)

 

#define parameters

 

params = {'learning_rate':0.001}

 

model= lgb.train(params, train_data, 100)

 

y_pred=model.predict(x_test)

 

for i in range(0,185):

 

   if y_pred[i]>=0.5:

 

   y_pred[i]=1

 

else:

 

   y_pred[i]=0

 

0.81621621621621621

 

回归问题示例代码:

 

 

import lightgbm as lgb

 

train_data=lgb.Dataset(x_train,label=y_train)

 

params = {'learning_rate':0.001}

 

model= lgb.train(params, train_data, 100)

 

from sklearn.metrics import mean_squared_error

 

rmse=mean_squared_error(y_pred,y_test)**0.5

 

参数:

 

  • num_iterations

    • 它定义了要执行的提升迭代次数

  • num_leaves

    • 此参数用于设置要在树中形成的叶子数

    • 在Light GBM的情况下,由于拆分是按逐叶子方式而不是深度方式进行的,因此num_leaves必须小于2 ^(max_depth),否则可能导致过拟合

  • min_data_in_leaf

    • 非常小的值可能导致过拟合

    • 它也是处理过拟合的最重要的参数之一

  • max_depth

    • 它指定树可以生长到的最大深度或级别

    • 此参数的值非常高可能会导致过拟合

  • bagging_fraction

    • 它用于指定每次迭代使用的数据比例

    • 此参数通常用于加速训练

  • max_bin

    • 定义特征值将被分桶的最大分箱数

    • 较小的max_bin值可以节省大量时间,因为它在离散分箱中存储特征值,这在计算开销上是便宜的

 

4.7 CatBoost

 

处理类别型变量是一个繁琐的过程,尤其是你有大量此类变量时。当你的类别变量有很多标签(即它们是高度基数)时,对它们执行one-hot编码会指数级的增加维度,会让数据集的使用变得非常困难。

 

CatBoost可以自动处理类别型变量,并且不需要像其他机器学习算法那样进行大量数据预处理。这篇文章详细解释了CatBoost。

 

示例代码:

 

CatBoost算法有效地处理类别型变量。因此,无需对变量执行one-hot编码。只需加载文件,估算缺失值,就可以了:

 

 

from catboost import CatBoostClassifier

 

model=CatBoostClassifier()

 

categorical_features_indices = np.where(df.dtypes != np.float)[0]

 

model.fit(x_train,y_train,cat_features=([ 0,  1, 2, 3, 4, 10]),eval_set=(x_test, y_test))

 

model.score(x_test,y_test)

 

0.80540540540540539

 

回归问题示例代码:

 

 

from catboost import CatBoostRegressor

 

model=CatBoostRegressor()

 

categorical_features_indices = np.where(df.dtypes != np.float)[0]

 

model.fit(x_train,y_train,cat_features=([ 0,  1, 2, 3, 4, 10]),eval_set=(x_test, y_test))

 

model.score(x_test,y_test)

 

参数:

 

  • loss_function

    • 定义用于训练的度量标准

  • iterations

    • 可以构建最多多少棵树

    • 树的最终数量可能小于或等于此数字

  • learning_rate

    • 定义学习率

    • 用于减少梯度步骤

  • border_count

    • 它指定数值型特征的拆分数

    • 它类似于max_bin参数

  • depth

    • 定义树的深度   

  • random_seed

    • 此参数类似于我们之前看到的'random_state'参数

    • 它是一个整数值,用于定义训练的随机种子

下面是决策树、AdaBoost、GBDT和XGBoost在UCI的Breast cancer数据集上的表现。

import pandas as pd
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import AdaBoostClassifier
from sklearn.ensemble import GradientBoostingClassifier
import xgboost 
from sklearn.metrics import accuracy_score
 
#读入乳腺癌数据集
data=load_breast_cancer()
x=pd.DataFrame(data.data)
y=data.target
#划分数据集
X_train,X_test,y_train,y_test=train_test_split(x,y,random_state=0,test_size=0.3)
 
# 度量单个决策树的准确性
tree = DecisionTreeClassifier(criterion='entropy', 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))
#Decision tree train/test accuracies 1.000/0.942
 
# Boosting分类器准确性
ada = AdaBoostClassifier(n_estimators=1000, learning_rate=0.1, random_state=0)
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 train/test accuracies 1.000/0.977
 
gbdt =GradientBoostingClassifier(n_estimators=1000, learning_rate=0.1, random_state=0)
gbdt= gbdt.fit(X_train, y_train)
y_train_pred = gbdt.predict(X_train)
y_test_pred = gbdt.predict(X_test)
gbdt_train = accuracy_score(y_train, y_train_pred)
gbdt_test = accuracy_score(y_test, y_test_pred)
print('GBDT train/test accuracies %.3f/%.3f' % (gbdt_train, gbdt_test)) 
# GBDT train/test accuracies 1.000/0.982
 
xgb =xgboost.XGBClassifier(n_estimators=1000, learning_rate=0.1)
xgb= xgb.fit(X_train, y_train)
y_train_pred = xgb.predict(X_train)
y_test_pred = xgb.predict(X_test)
xgb_train = accuracy_score(y_train, y_train_pred)
xgb_test = accuracy_score(y_test, y_test_pred)
print('XGBoost train/test accuracies %.3f/%.3f' % (xgb_train, xgb_test)) 
# XGBoost train/test accuracies 1.000/0.982

其输出结果是

Decision tree train/test accuracies 1.000/0.971
AdaBoost train/test accuracies 1.000/0.977
GBDT train/test accuracies 1.000/0.982
XGBoost train/test accuracies 1.000/0.982

3.Bagging和Boosting的区别
1)偏差—方差
Boosting:从偏差—方差分解角度看,降低偏差。 
Bagging:从偏差—方差分解角度看,降低方差。

2)样本选择:
Boosting:每一轮的训练集不变,只是训练集中每个样例在分类器中的权重发生变化.而权值是根据上一轮的分类结果进行调整。 
Bagging:训练集是在原始集中有放回选取的,从原始集中选出的各轮训练集之间是独立的。

3)样例权重:
Boosting:根据错误率不断调整样例的权值,错误率越大则权重越大。 
Bagging:使用均匀取样,每个样例的权重相等

4)基学习器权重:
Boosting:每个弱分类器都有相应的权重,对于分类误差小的分类器会有更大的权重. 
Bagging:所有弱分类器的权重相等.

5)串、并行计算:
Boosting:串行,各个及学习器只能顺序生成,因为后一个模型参数需要前一轮模型的结果。 
Bagging:各个预测函数可以并行生成。
 

结语

 

集成模型可以指数级地提升模型的性能,有时可以成为第一名和第二名之间的决定因素!在本文中,我们介绍了各种集成学习技术,并了解了这些技术如何应用于机器学习算法。此外,我们在贷款预测数据集上运用了算法。

 

本文为你提供了此主题的扎实理解。如果还有任何建议或问题,请分享在下面的评论部分。此外,我鼓励你实现这些算法,并与我们分享你的结果!

 

原文标题:

A Comprehensive Guide to Ensemble Learning(with Python codes)

原文链接:

https://www.analyticsvidhya.com/blog/2018/06/comprehensive-guide-for-ensemble-models/

译者简介:和中华,留德软件工程硕士。由于对机器学习感兴趣,硕士论文选择了利用遗传算法思想改进传统kmeans。目前在杭州进行大数据相关实践。加入数据派THU希望为IT同行们尽自己一份绵薄之力,也希望结交许多志趣相投的小伙伴。

版权声明:本号内容部分来自互联网,转载请注明原文链接和作者,如有侵权或出处有误请和我们联系。

  • 12
    点赞
  • 109
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

CtrlZ1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值