task5 模型融合 打卡

不想你离开。 提交于 2020-04-05 17:13:25

5.1 模型融合目标
对于多种调参完成的模型进行模型融合。

完成对于多种模型的融合,提交融合结果并打卡。

5.2 内容介绍
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。

简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法
5.3 Stacking相关理论介绍

  1. 什么是 stacking
    简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。

    将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。

上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。

在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

  1. 如何进行 stacking
    引用机器学习书上的定义:

    过程1-3 是训练出来个体学习器,也就是初级学习器。
    过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
    过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
    3)Stacking的方法讲解
    首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。

Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2

Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1

Model1_1 模型训练:

Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2

Model1_2 模型训练:

Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.

这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。

Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。

次级模型尽量选择简单的线性模型
利用K折交叉验证
K-折交叉验证: 训练:

5.4 代码示例
5.4.1 回归\分类概率-融合:
1)简单加权平均,结果直接融合
5.1 模型融合目标
对于多种调参完成的模型进行模型融合。

完成对于多种模型的融合,提交融合结果并打卡。

5.2 内容介绍
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。

简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法
5.3 Stacking相关理论介绍

  1. 什么是 stacking
    简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。

    将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。

上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。

在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

  1. 如何进行 stacking
    引用机器学习书上的定义:

    过程1-3 是训练出来个体学习器,也就是初级学习器。
    过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
    过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
    3)Stacking的方法讲解
    首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。

Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2

Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1

Model1_1 模型训练:

Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2

Model1_2 模型训练:

Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.

这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。

Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。

次级模型尽量选择简单的线性模型
利用K折交叉验证
K-折交叉验证: 训练:

5.4 代码示例
5.4.1 回归\分类概率-融合:
1)简单加权平均,结果直接融合

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

y_test_true 代表第模型的真实值

y_test_true = [1, 3, 2, 6]
import numpy as np
import pandas as pd

定义结果的加权平均函数

def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
Weighted_result = w[0]pd.Series(test_pre1)+w[1]pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
return Weighted_result
from sklearn import metrics

各模型的预测结果计算MAE

print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
print('Pred3 MAE:',metrics.mean_absolute_error(y_test_在这里插入代码片true, test_pre3))
Pred1 MAE: 0.175
Pred2 MAE: 0.075
Pred3 MAE: 0.1

根据加权计算MAE

w = [0.3,0.4,0.3] # 定义比重权值
Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))

2) Stacking融合(回归):
from sklearn import linear_model

def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
return Stacking_result

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

train_reg1 = [3.2, 8.2, 9.1, 5.2]
train_reg2 = [2.9, 8.1, 9.0, 4.9]
train_reg3 = [3.1, 7.9, 9.2, 5.0]

y_test_true 代表第模型的真实值

y_train_true = [3, 8, 9, 5]

test_pre1 = [1.2, 3.2, 2.1, 6.2]
test_pre2 = [0.9, 3.1, 2.0, 5.9]
test_pre3 = [1.1, 2.9, 2.2, 6.0]

y_test_true 代表第模型的真实值

y_test_true = [1, 3, 2, 6]

model_L2= linear_model.LinearRegression()
Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
test_pre1,test_pre2,test_pre3,model_L2)
print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))

可以发现模型结果相对于之前有进一步的提升,这是我们需要注意的一点是,对于第二层Stacking的模型不宜选取的过于复杂,这样会导致模型在训练集上过拟合,从而使得在测试集上并不能达到很好的效果。

5.4.2 分类模型融合:
对于分类,同样的可以使用融合方法,比如简单投票,Stacking...
from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
Datawhale 零基础入门数据挖掘-Task5 模型融合
五、模型融合
Tip:此部分为零基础入门数据挖掘的 Task5 模型融合 部分,带你来了解各种模型结果的融合方式,在比赛的攻坚时刻冲刺Top,欢迎大家后续多多交流。

赛题:零基础入门数据挖掘 - 二手车交易价格预测

地址:https://tianchi.aliyun.com/competition/entrance/231784/introduction?spm=5176.12281957.1004.1.38b02448ausjSX

5.1 模型融合目标
对于多种调参完成的模型进行模型融合。

完成对于多种模型的融合,提交融合结果并打卡。

5.2 内容介绍
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。

简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法
5.3 Stacking相关理论介绍

  1. 什么是 stacking
    简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。

Image

将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。

上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。

在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

  1. 如何进行 stacking
    算法示意图如下:

Image

引用自 西瓜书《机器学习》

过程1-3 是训练出来个体学习器,也就是初级学习器。
过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
3)Stacking的方法讲解
首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。

Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2

Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1

Model1_1 模型训练:







X
t
r
a
i
n






Model1_1 Train








Y
T
r
u
e





训练后的模型 Model1_1 分别在 train 和 test 上预测,得到预测标签分别是P1,T1







X
t
r
a
i
n






Model1_1 Predict








P
1











X
t
e
s
t






Model1_1 Predict








T
1





Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2

Model1_2 模型训练:







X
t
r
a
i
n






Model1_2 Train








Y
T
r
u
e





训练后的模型 Model1_2 分别在 train 和 test 上预测,得到预测标签分别是P2,T2







X
t
r
a
i
n






Model1_2 Predict








P
2











X
t
e
s
t






Model1_2 Predict








T
2





Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.

Train_2







P
1


P
2






a
n
d
Test_2







T
1


T
2





再用 次级模型 Model2 以真实训练集标签为标签训练,以train2为特征进行训练,预测test2,得到最终的测试集预测的标签列
Y
P
r
e

Train_2







P
1


P
2






Model2 Train








Y
T
r
u
e





Test_2







T
1


T
2






Model1_2 Predict








Y
P
r
e





这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。

Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。

次级模型尽量选择简单的线性模型
利用K折交叉验证
K-折交叉验证: 训练:

Image

预测:

Image

5.4 代码示例
5.4.1 回归\分类概率-融合:
1)简单加权平均,结果直接融合

1

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

2
test_pre1 = [1.2, 3.2, 2.1, 6.2]
3
test_pre2 = [0.9, 3.1, 2.0, 5.9]
4
test_pre3 = [1.1, 2.9, 2.2, 6.0]
5

6

y_test_true 代表第模型的真实值

7
y_test_true = [1, 3, 2, 6]

1
import numpy as np
2
import pandas as pd
3

4

定义结果的加权平均函数

5
def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
6
Weighted_result = w[0]pd.Series(test_pre1)+w[1]pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
7
return Weighted_result

1
from sklearn import metrics
2

各模型的预测结果计算MAE

3
print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
4
print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
5
print('Pred3 MAE:',metrics.mean_absolute_error(y_test_true, test_pre3))
Pred1 MAE: 0.175
Pred2 MAE: 0.075
Pred3 MAE: 0.1

1

根据加权计算MAE

2
w = [0.3,0.4,0.3] # 定义比重权值
3
Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
4
print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))
Weighted_pre MAE: 0.0575
可以发现加权结果相对于之前的结果是有提升的,这种我们称其为简单的加权平均。

还有一些特殊的形式,比如mean平均,median平均

1

定义结果的加权平均函数

2
def Mean_method(test_pre1,test_pre2,test_pre3):
3
Mean_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).mean(axis=1)
4
return Mean_result

1
Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3)
2
print('Mean_pre MAE:',metrics.mean_absolute_error(y_test_true, Mean_pre))
Mean_pre MAE: 0.0666666666667

1

定义结果的加权平均函数

2
def Median_method(test_pre1,test_pre2,test_pre3):
3
Median_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).median(axis=1)
4
return Median_result

1
Median_pre = Median_method(test_pre1,test_pre2,test_pre3)
2
print('Median_pre MAE:',metrics.mean_absolute_error(y_test_true, Median_pre))
Median_pre MAE: 0.075
2) Stacking融合(回归):

1
from sklearn import linear_model
2

3
def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
4
model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
5
Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
6
return Stacking_result

1

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

2
train_reg1 = [3.2, 8.2, 9.1, 5.2]
3
train_reg2 = [2.9, 8.1, 9.0, 4.9]
4
train_reg3 = [3.1, 7.9, 9.2, 5.0]
5

y_test_true 代表第模型的真实值

6
y_train_true = [3, 8, 9, 5]
7

8
test_pre1 = [1.2, 3.2, 2.1, 6.2]
9
test_pre2 = [0.9, 3.1, 2.0, 5.9]
10
test_pre3 = [1.1, 2.9, 2.2, 6.0]
11

12

y_test_true 代表第模型的真实值

13
y_test_true = [1, 3, 2, 6]

1
model_L2= linear_model.LinearRegression()
2
Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
3
test_pre1,test_pre2,test_pre3,model_L2)
4
print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))
Stacking_pre MAE: 0.0421348314607
可以发现模型结果相对于之前有进一步的提升,这是我们需要注意的一点是,对于第二层Stacking的模型不宜选取的过于复杂,这样会导致模型在训练集上过拟合,从而使得在测试集上并不能达到很好的效果。

5.4.2 分类模型融合:
对于分类,同样的可以使用融合方法,比如简单投票,Stacking...

from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
1
from sklearn.datasets import make_blobs
2
from sklearn import datasets
3
from sklearn.tree import DecisionTreeClassifier
4
import numpy as np
5
from sklearn.ensemble import RandomForestClassifier
6
from sklearn.ensemble import VotingClassifier
7
from xgboost import XGBClassifier
8
from sklearn.linear_model import LogisticRegression
9
from sklearn.svm import SVC
10
from sklearn.model_selection import train_test_split
11
from sklearn.datasets import make_moons
12
from sklearn.metrics import accuracy_score,roc_auc_score
13
from sklearn.model_selection import cross_val_score
14
from sklearn.model_selection import StratifiedKFold

1)Voting投票机制:
Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。
'''
硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
'''
iris = datasets.load_iris()

x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)

clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.7,
colsample_bytree=0.6, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1)

硬投票

eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='hard')
for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

'''
软投票:和硬投票原理相同,增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。
'''
x=iris.data
y=iris.target
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)

clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.8,
colsample_bytree=0.8, objective='binary:logistic')
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
min_samples_leaf=63,oob_score=True)
clf3 = SVC(C=0.1, probability=True)

软投票

eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='soft', weights=[2, 1, 1])
clf1.fit(x_train, y_train)

for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

Datawhale 零基础入门数据挖掘-Task5 模型融合
五、模型融合
Tip:此部分为零基础入门数据挖掘的 Task5 模型融合 部分,带你来了解各种模型结果的融合方式,在比赛的攻坚时刻冲刺Top,欢迎大家后续多多交流。

赛题:零基础入门数据挖掘 - 二手车交易价格预测

地址:https://tianchi.aliyun.com/competition/entrance/231784/introduction?spm=5176.12281957.1004.1.38b02448ausjSX

5.1 模型融合目标
对于多种调参完成的模型进行模型融合。

完成对于多种模型的融合,提交融合结果并打卡。

5.2 内容介绍
模型融合是比赛后期一个重要的环节,大体来说有如下的类型方式。

简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合
stacking/blending:
构建多层模型,并利用预测结果再拟合预测。
boosting/bagging(在xgboost,Adaboost,GBDT中已经用到):
多树的提升方法
5.3 Stacking相关理论介绍

  1. 什么是 stacking
    简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。

Image

将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。

上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。

在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

  1. 如何进行 stacking
    算法示意图如下:

Image

引用自 西瓜书《机器学习》

过程1-3 是训练出来个体学习器,也就是初级学习器。
过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
3)Stacking的方法讲解
首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。

Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2

Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1

Model1_1 模型训练:







X
t
r
a
i
n






Model1_1 Train








Y
T
r
u
e





训练后的模型 Model1_1 分别在 train 和 test 上预测,得到预测标签分别是P1,T1







X
t
r
a
i
n






Model1_1 Predict








P
1











X
t
e
s
t






Model1_1 Predict








T
1





Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2

Model1_2 模型训练:







X
t
r
a
i
n






Model1_2 Train








Y
T
r
u
e





训练后的模型 Model1_2 分别在 train 和 test 上预测,得到预测标签分别是P2,T2







X
t
r
a
i
n






Model1_2 Predict








P
2











X
t
e
s
t






Model1_2 Predict








T
2





Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.

Train_2







P
1


P
2






a
n
d
Test_2







T
1


T
2





再用 次级模型 Model2 以真实训练集标签为标签训练,以train2为特征进行训练,预测test2,得到最终的测试集预测的标签列
Y
P
r
e

Train_2







P
1


P
2






Model2 Train








Y
T
r
u
e





Test_2







T
1


T
2






Model1_2 Predict








Y
P
r
e





这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。

Stacking本质上就是这么直接的思路,但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降,因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。

次级模型尽量选择简单的线性模型
利用K折交叉验证
K-折交叉验证: 训练:

Image

预测:

Image

5.4 代码示例
5.4.1 回归\分类概率-融合:
1)简单加权平均,结果直接融合

1

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

2
test_pre1 = [1.2, 3.2, 2.1, 6.2]
3
test_pre2 = [0.9, 3.1, 2.0, 5.9]
4
test_pre3 = [1.1, 2.9, 2.2, 6.0]
5

6

y_test_true 代表第模型的真实值

7
y_test_true = [1, 3, 2, 6]

1
import numpy as np
2
import pandas as pd
3

4

定义结果的加权平均函数

5
def Weighted_method(test_pre1,test_pre2,test_pre3,w=[1/3,1/3,1/3]):
6
Weighted_result = w[0]pd.Series(test_pre1)+w[1]pd.Series(test_pre2)+w[2]*pd.Series(test_pre3)
7
return Weighted_result

1
from sklearn import metrics
2

各模型的预测结果计算MAE

3
print('Pred1 MAE:',metrics.mean_absolute_error(y_test_true, test_pre1))
4
print('Pred2 MAE:',metrics.mean_absolute_error(y_test_true, test_pre2))
5
print('Pred3 MAE:',metrics.mean_absolute_error(y_test_true, test_pre3))
Pred1 MAE: 0.175
Pred2 MAE: 0.075
Pred3 MAE: 0.1

1

根据加权计算MAE

2
w = [0.3,0.4,0.3] # 定义比重权值
3
Weighted_pre = Weighted_method(test_pre1,test_pre2,test_pre3,w)
4
print('Weighted_pre MAE:',metrics.mean_absolute_error(y_test_true, Weighted_pre))
Weighted_pre MAE: 0.0575
可以发现加权结果相对于之前的结果是有提升的,这种我们称其为简单的加权平均。

还有一些特殊的形式,比如mean平均,median平均

1

定义结果的加权平均函数

2
def Mean_method(test_pre1,test_pre2,test_pre3):
3
Mean_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).mean(axis=1)
4
return Mean_result

1
Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3)
2
print('Mean_pre MAE:',metrics.mean_absolute_error(y_test_true, Mean_pre))
Mean_pre MAE: 0.0666666666667

1

定义结果的加权平均函数

2
def Median_method(test_pre1,test_pre2,test_pre3):
3
Median_result = pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).median(axis=1)
4
return Median_result

1
Median_pre = Median_method(test_pre1,test_pre2,test_pre3)
2
print('Median_pre MAE:',metrics.mean_absolute_error(y_test_true, Median_pre))
Median_pre MAE: 0.075
2) Stacking融合(回归):

1
from sklearn import linear_model
2

3
def Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,test_pre1,test_pre2,test_pre3,model_L2= linear_model.LinearRegression()):
4
model_L2.fit(pd.concat([pd.Series(train_reg1),pd.Series(train_reg2),pd.Series(train_reg3)],axis=1).values,y_train_true)
5
Stacking_result = model_L2.predict(pd.concat([pd.Series(test_pre1),pd.Series(test_pre2),pd.Series(test_pre3)],axis=1).values)
6
return Stacking_result

1

生成一些简单的样本数据,test_prei 代表第i个模型的预测值

2
train_reg1 = [3.2, 8.2, 9.1, 5.2]
3
train_reg2 = [2.9, 8.1, 9.0, 4.9]
4
train_reg3 = [3.1, 7.9, 9.2, 5.0]
5

y_test_true 代表第模型的真实值

6
y_train_true = [3, 8, 9, 5]
7

8
test_pre1 = [1.2, 3.2, 2.1, 6.2]
9
test_pre2 = [0.9, 3.1, 2.0, 5.9]
10
test_pre3 = [1.1, 2.9, 2.2, 6.0]
11

12

y_test_true 代表第模型的真实值

13
y_test_true = [1, 3, 2, 6]

1
model_L2= linear_model.LinearRegression()
2
Stacking_pre = Stacking_method(train_reg1,train_reg2,train_reg3,y_train_true,
3
test_pre1,test_pre2,test_pre3,model_L2)
4
print('Stacking_pre MAE:',metrics.mean_absolute_error(y_test_true, Stacking_pre))
Stacking_pre MAE: 0.0421348314607
可以发现模型结果相对于之前有进一步的提升,这是我们需要注意的一点是,对于第二层Stacking的模型不宜选取的过于复杂,这样会导致模型在训练集上过拟合,从而使得在测试集上并不能达到很好的效果。

5.4.2 分类模型融合:
对于分类,同样的可以使用融合方法,比如简单投票,Stacking...

from sklearn.datasets import make_blobs
from sklearn import datasets
from sklearn.tree import DecisionTreeClassifier
import numpy as np
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import VotingClassifier
from xgboost import XGBClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.svm import SVC
from sklearn.model_selection import train_test_split
from sklearn.datasets import make_moons
from sklearn.metrics import accuracy_score,roc_auc_score
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import StratifiedKFold
1
from sklearn.datasets import make_blobs
2
from sklearn import datasets
3
from sklearn.tree import DecisionTreeClassifier
4
import numpy as np
5
from sklearn.ensemble import RandomForestClassifier
6
from sklearn.ensemble import VotingClassifier
7
from xgboost import XGBClassifier
8
from sklearn.linear_model import LogisticRegression
9
from sklearn.svm import SVC
10
from sklearn.model_selection import train_test_split
11
from sklearn.datasets import make_moons
12
from sklearn.metrics import accuracy_score,roc_auc_score
13
from sklearn.model_selection import cross_val_score
14
from sklearn.model_selection import StratifiedKFold
1)Voting投票机制:
Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。

1
'''
2
硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
3
'''
4
iris = datasets.load_iris()
5

6
x=iris.data
7
y=iris.target
8
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
9

10
clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.7,
11
colsample_bytree=0.6, objective='binary:logistic')
12
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
13
min_samples_leaf=63,oob_score=True)
14
clf3 = SVC(C=0.1)
15

16

硬投票

17
eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='hard')
18
for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
19
scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
20
print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

1
'''
2
软投票:和硬投票原理相同,增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。
3
'''
4
x=iris.data
5
y=iris.target
6
x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.3)
7

8
clf1 = XGBClassifier(learning_rate=0.1, n_estimators=150, max_depth=3, min_child_weight=2, subsample=0.8,
9
colsample_bytree=0.8, objective='binary:logistic')
10
clf2 = RandomForestClassifier(n_estimators=50, max_depth=1, min_samples_split=4,
11
min_samples_leaf=63,oob_score=True)
12
clf3 = SVC(C=0.1, probability=True)
13

14

软投票

15
eclf = VotingClassifier(estimators=[('xgb', clf1), ('rf', clf2), ('svc', clf3)], voting='soft', weights=[2, 1, 1])
16
clf1.fit(x_train, y_train)
17

18
for clf, label in zip([clf1, clf2, clf3, eclf], ['XGBBoosting', 'Random Forest', 'SVM', 'Ensemble']):
19
scores = cross_val_score(clf, x, y, cv=5, scoring='accuracy')
20
print("Accuracy: %0.2f (+/- %0.2f) [%s]" % (scores.mean(), scores.std(), label))

2)分类的Stacking\Blending融合:
'''
5-Fold Stacking
'''
from sklearn.ensemble import RandomForestClassifier
from sklearn.ensemble import ExtraTreesClassifier,GradientBoostingClassifier
import pandas as pd

创建训练的数据集

data_0 = iris.data
data = data_0[:100,:]

target_0 = iris.target
target = target_0[:100]

模型融合中使用到的各个单模型

clfs = [LogisticRegression(solver='lbfgs'),
RandomForestClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='gini'),
ExtraTreesClassifier(n_estimators=5, n_jobs=-1, criterion='entropy'),
GradientBoostingClassifier(learning_rate=0.05, subsample=0.5, max_depth=6, n_estimators=5)]

切分一部分数据作为测试集

X, X_predict, y, y_predict = train_test_split(data, target, test_size=0.3, random_state=2020)

dataset_blend_train = np.zeros((X.shape[0], len(clfs)))
dataset_blend_test = np.zeros((X_predict.shape[0], len(clfs)))

5折stacking

n_splits = 5
skf = StratifiedKFold(n_splits)
skf = skf.split(X, y)

for j, clf in enumerate(clfs):
#依次训练各个单模型
dataset_blend_test_j = np.zeros((X_predict.shape[0], 5))
for i, (train, test) in enumerate(skf):
#5-Fold交叉训练,使用第i个部分作为预测,剩余的部分来训练模型,获得其预测的输出作为第i部分的新特征。
X_train, y_train, X_test, y_test = X[train], y[train], X[test], y[test]
clf.fit(X_train, y_train)
y_submission = clf.predict_proba(X_test)[:, 1]
dataset_blend_train[test, j] = y_submission
dataset_blend_test_j[:, i] = clf.predict_proba(X_predict)[:, 1]
#对于测试集,直接用这k个模型的预测值均值作为新的特征。
dataset_blend_test[:, j] = dataset_blend_test_j.mean(1)
print("val auc Score: %f" % roc_auc_score(y_predict, dataset_blend_test[:, j]))

clf = LogisticRegression(solver='lbfgs')
clf.fit(dataset_blend_train, y)
y_submission = clf.predict_proba(dataset_blend_test)[:, 1]

print("Val auc Score of Stacking: %f" % (roc_auc_score(y_predict, y_submission)))

Blending优点在于:
1.比stacking简单(因为不用进行k次的交叉验证来获得stacker feature)
2.避开了一个信息泄露问题:generlizers和stacker使用了不一样的数据集
缺点在于:

1.使用了很少的数据(第二阶段的blender只使用training set10%的量)
2.blender可能会过拟合
3.stacking使用多次的交叉验证会比较稳健 '''

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!