Quote:
在此文中介绍到的多种机器学习类型中,我们通常会用到其中的 2 个甚至 2 个以上。如果我们要同时利用这些个模型,就需要将分别的训练结果结合起来作为总的训练结果。
此过程称之为 “ 模型融合 “
面向对象:多种调参后的模型。接下来介绍三种提升分数较为显著的方法:
简单的加权融合
- 回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean);
- 分类:投票(Voting)
- 综合:排序融合(Rank averaging),log融合
加权平均
面向模型:回归 \ 分类概率模型
1 | ## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值 |
加权平均函数的定义
1 | import numpy as np |
模型训练【3个】
1 | from sklearn import metrics |
加权计算
1 | ## 根据加权计算MAE |
Result:
1 | Weighted_pre MAE: 0.0575 |
mean 平均
1 | ## 定义结果的加权平均函数 |
1 | Mean_pre = Mean_method(test_pre1,test_pre2,test_pre3) |
Result:
1 | Mean_pre MAE: 0.0666666666667 |
median平均
1 | ## 定义结果的加权平均函数 |
1 | Median_pre = Median_method(test_pre1,test_pre2,test_pre3) |
Result:
1 | Median_pre MAE: 0.075 |
Voting投票机制
Voting即投票机制,分为软投票和硬投票两种,其原理采用少数服从多数的思想。
面向模型:分类模型
1 | from sklearn.datasets import make_blobs |
1 | ''' |
1 | ''' |
stacking / blending
以两层为例,第一层由多个基学习器组成,其输入为原始训练集,第二层的模型则是以第一层基学习器的输出作为训练集进行再训练,从而得到完整的stacking模型, stacking两层模型都使用了全部的训练数据。
理论介绍
简单来说 stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。
将个体学习器结合在一起的时候使用的方法叫做结合策略。对于分类问题,我们可以使用投票法来选择输出最多的类。对于回归问题,我们可以将分类器输出的结果求平均值。
上面说的投票法和平均法都是很有效的结合策略,还有一种结合策略是使用另外一个机器学习算法来将个体机器学习器的结果结合在一起,这个方法就是Stacking。
在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器(meta-learner),次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。
算法

- 过程1-3 是训练出来个体学习器,也就是初级学习器。
- 过程5-9是 使用训练出来的个体学习器来得预测的结果,这个预测的结果当做次级学习器的训练集。
- 过程11 是用初级学习器预测的结果训练出次级学习器,得到我们最后训练的模型。
推导 & 解析【三步走战略】
首先,我们先从一种“不那么正确”但是容易懂的Stacking方法讲起。
Stacking模型本质上是一种分层的结构,这里简单起见,只分析二级Stacking.假设我们有2个基模型 Model1_1、Model1_2 和 一个次级模型Model2
Step 1. 基模型 Model1_1,对训练集train训练,然后用于预测 train 和 test 的标签列,分别是P1,T1
Model1_1 模型训练:
$$
\left(\begin{array}{c}{\vdots} \ {X_{train}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_1 Train} }\left(\begin{array}{c}{\vdots} \ {Y}_{True} \ {\vdots}\end{array}\right)
$$
训练后的模型 Model1_1 分别在 train 和 test 上预测,得到预测标签分别是P1,T1
$$
\left(\begin{array}{c}{\vdots} \ {X_{train}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_1 Predict} }\left(\begin{array}{c}{\vdots} \ {P}_{1} \ {\vdots}\end{array}\right)
$$
$$
\left(\begin{array}{c}{\vdots} \ {X_{test}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_1 Predict} }\left(\begin{array}{c}{\vdots} \ {T_{1}} \ {\vdots}\end{array}\right)
$$
Step 2. 基模型 Model1_2 ,对训练集train训练,然后用于预测train和test的标签列,分别是P2,T2
Model1_2 模型训练:
$$
\left(\begin{array}{c}{\vdots} \ {X_{train}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_2 Train} }\left(\begin{array}{c}{\vdots} \ {Y}_{True} \ {\vdots}\end{array}\right)
$$
训练后的模型 Model1_2 分别在 train 和 test 上预测,得到预测标签分别是P2,T2
$$
\left(\begin{array}{c}{\vdots} \ {X_{train}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_2 Predict} }\left(\begin{array}{c}{\vdots} \ {P}_{2} \ {\vdots}\end{array}\right)
$$
$$
\left(\begin{array}{c}{\vdots} \ {X_{test}} \ {\vdots}\end{array}\right) \overbrace{\Longrightarrow}^{\ text {Model1_2 Predict} }\left(\begin{array}{c}{\vdots} \ {T_{2}} \ {\vdots}\end{array}\right)
$$
Step 3. 分别把P1,P2以及T1,T2合并,得到一个新的训练集和测试集train2,test2.
$$
\overbrace{\left(\begin{array}{c}{\vdots} \ {P_{1}} \ {\vdots}\end{array} \begin{array}{c}{\vdots} \ {P_{2}} \ {\vdots}\end{array} \right)} ^ {text {Train_2 }}
and
\overbrace{\left(\begin{array}{c}{\vdots} \ {T_{1}} \ {\vdots}\end{array} \begin{array}{c}{\vdots} \ {T_{2}} \ {\vdots}\end{array} \right)}^{text {Test_2 }}
$$
再用 次级模型 Model2 以真实训练集标签为标签训练,以train2为特征进行训练,预测test2,得到最终的测试集预测的标签列 $Y_{Pre}$。
$$
\overbrace{\left(\begin{array}{c}{\vdots} \ {P_{1}} \ {\vdots}\end{array} \begin{array}{c}{\vdots} \ {P_{2}} \ {\vdots}\end{array} \right)}^{\ text {Train_2 }} \overbrace{\Longrightarrow}^{\text {Model2 Train} }\left(\begin{array}{c}{\vdots} \ {Y}_{True} \ {\vdots}\end{array}\right)
$$
$$
\overbrace{\left(\begin{array}{c}{\vdots} \ {T_{1}} \ {\vdots}\end{array} \begin{array}{c}{\vdots} \ {T_{2}} \ {\vdots}\end{array} \right)}^{\ text {Test_2 }} \overbrace{\Longrightarrow}^{\ text {Model1_2 Predict} }\left(\begin{array}{c}{\vdots} \ {Y}_{Pre} \ {\vdots}\end{array}\right)
$$
这就是我们两层堆叠的一种基本的原始思路想法。在不同模型预测的结果基础上再加一层模型,进行再训练,从而得到模型最终的预测。
Stacking本质上就是这么直接的思路。
但是直接这样有时对于如果训练集和测试集分布不那么一致的情况下是有一点问题的,其问题在于用初始模型训练的标签再利用真实标签进行再训练,毫无疑问会导致一定的模型过拟合训练集,这样或许模型在测试集上的泛化能力或者说效果会有一定的下降。
因此现在的问题变成了如何降低再训练的过拟合性,这里我们一般有两种方法。
- 次级模型尽量选择简单的线性模型
- 利用K折交叉验证
K-折交叉验证:
训练:
预测:
面向模型:回归 \ 分类概率模型
1 | from sklearn import linear_model |
1 | ## 生成一些简单的样本数据,test_prei 代表第i个模型的预测值 |
1 | model_L2= linear_model.LinearRegression() |
Result:
1 | Stacking_pre MAE: 0.0421348314607 |
可以发现模型结果相对于之前有进一步的提升,这是我们需要注意的一点是,对于第二层Stacking的模型不宜选取的过于复杂,这样会导致模型在训练集上过拟合,从而使得在测试集上并不能达到很好的效果。
Blending
其实和Stacking是一种类似的多层模型融合的形式
其主要思路是把原始的训练集先分成两部分,比如70%的数据作为新的训练集,剩下30%的数据作为测试集。
在第一层,我们在这70%的数据上训练多个模型,然后去预测那30%数据的label,同时也预测test集的label。
在第二层,我们就直接用这30%数据在第一层预测的结果做为新特征继续训练,然后用test集第一层预测的label做特征,用第二层训练的模型做进一步预测
其优点在于:
- 比stacking简单(因为不用进行k次的交叉验证来获得stacker feature)
- 避开了一个信息泄露问题:generlizers和stacker使用了不一样的数据集
缺点在于:
- 使用了很少的数据(第二阶段的blender只使用training set10%的量)
- blender可能会过拟合
- stacking使用多次的交叉验证会比较稳健
boosting / bagging
在xgboost,Adaboost,GBDT中已经用到
- 多树的提升方法
Reference: Modeling and tuning
Others Methods
将特征放进模型中预测,并将预测结果变换并作为新的特征加入原有特征中再经过模型预测结果 (Stacking变化)
可以反复预测多次将结果加入最后的特征中
1 | def Ensemble_add_feature(train,test,target,clfs): |
1 | from sklearn.model_selection import cross_val_score, train_test_split |
Conclusion:
比赛的融合是提分和提升模型鲁棒性的一种重要方法:
结果层面的融合,这种是最常见的融合方法,其可行的融合方法也有很多,比如根据结果的得分进行加权融合,还可以做Log,exp处理等。在做结果融合的时候,有一个很重要的条件是模型结果的得分要比较近似,然后结果的差异要比较大,这样的结果融合往往有比较好的效果提升。
特征层面的融合,这个层面其实感觉不叫融合,准确说可以叫分割,很多时候如果我们用同种模型训练,可以把特征进行切分给不同的模型,然后在后面进行模型或者结果融合有时也能产生比较好的效果。
模型层面的融合,模型层面的融合可能就涉及模型的堆叠和设计,比如加Staking层,部分模型的结果作为特征输入等,这些就需要多实验和思考了,基于模型层面的融合最好不同模型类型要有一定的差异,用同种模型不同的参数的收益一般是比较小的。