Python数据科学竞赛模型融合

模型融合

模型融合采用的的思想,即多个模型的组合可以改善整体的表现。集成模型是一种能在各种的机器学习任务上提高准确率的强有力技术。模型融合是kaggle竞赛后期一个重要的环节,大体来说有如下的类型方式:

1. 简单加权融合:
回归(分类概率):算术平均融合(Arithmetic mean),几何平均融合(Geometric mean)
分类:投票(Voting)
综合:排序融合(Rank averaging),log融合

2. stacking/blending:
构建多层模型,并利用预测结果再拟合预测

3. boosting/bagging:
多树的提升方法,在xgboost,Adaboost,GBDT等中已经用到

平均法(Averaging)

基本思想:对于回归问题,一个简单直接的思路是取平均。稍稍改进的方法是进行加权平均。权值可以用排序的方法确定,举个例子,比如A、B、C三种基本模型,模型效果进行排名,假设排名分别是1,2,3,那么给这三个模型赋予的权值分别是3/6、2/6、1/6。

平均法或加权平均法看似简单,其实后面的高级算法也可以说是基于此而产生的,Bagging或者Boosting都是一种把许多弱分类器这样融合成强分类器的思想。

  1. 简单算术平均法:Averaging方法就多个模型预测的结果进行平均。这种方法既可以用于回归问题,也可以用于对分类问题的概率进行平均。
  2. 加权算术平均法:这种方法是平均法的扩展。考虑不同模型的能力不同,对最终结果的贡献也有差异,需要用权重来表征不同模型的重要性importance。

投票法(voting)

基本思想:假设对于一个二分类问题,有3个基础模型,现在我们可以在这些基学习器的基础上得到一个投票的分类器,把票数最多的类作为我们要预测的类别。

  1. 绝对多数投票法:最终结果必须在投票中占一半以上。
  2. 相对多数投票法:最终结果在投票中票数最多。
  3. 加权投票法
  4. 硬投票:对多个模型直接进行投票,不区分模型结果的相对重要度,最终投票数最多的类为最终被预测的类。
  5. 软投票:增加了设置权重的功能,可以为不同模型设置不同权重,进而区别模型不同的重要度。

投票法实现代码:`

from sklearn.tree import DecisionTreeClassifier
from sklearn.neighbors import KNeighborsClassifier
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import VotingClassifier

model1 = LogisticRegression(random_state=2020)
model2 = DecisionTreeClassifier(random_state=2020)
model = VotingClassifier(estimators=[('lr', model1), ('dt', model2)], voting='hard')
model.fit(x_train, y_train)
model.score(x_test, y_test)

堆叠法(Stacking)

基本思想:stacking 就是当用初始训练数据学习出若干个基学习器后,将这几个学习器的预测结果作为新的训练集,来学习一个新的学习器。对不同模型预测的结果再进行建模。
在这里插入图片描述
在stacking方法中,我们把个体学习器叫做初级学习器,用于结合的学习器叫做次级学习器或元学习器,次级学习器用于训练的数据叫做次级训练集。次级训练集是在训练集上用初级学习器得到的。

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

  1. 次级模型尽量选择简单的线性模型,但是经实践线性模型效果并不好,推荐使用LightGBM
  2. 利用K折交叉验证

调用APi实现stacking:

扫描二维码关注公众号,回复: 12114153 查看本文章
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()
# 使用5折交叉验证结果
results10 = stacker.validate(k=5,scorer=mean_absolute_error)

手动实现:只创建一个基学习器为例:

from sklearn.model_selection import StratifiedKFold,KFold,RepeatedKFold
import xgboost.sklearn import XGBClassifier
import numpy as np

skf = StratifiedKFold(n_splits = 5, shuffle = True ,random_state=16)
oof_xgb = np.zeros(len(train))  #创建数组
pre_xgb = np.zeros(len(test))

for k,(train_in,test_in) in enumerate(skf.split(train,train_y)):
    X_train,X_test,y_train,y_test = X[train_in],X[test_in],y[train_in],y[test_in]
    params = {
    
    'learning_rate': 0.008, 
              'n_estimators': 1000
              'max_depth': 5,
              'subsample': 0.8, 
              'colsample_bytree': 0.8, 
              'objective':'binary:logistic',
              'eval_metric':'auc',
              'silent': True, 
              'nthread': 4,
              }
    # train
    clf = XGBClassifier(params)
    clf.fit(trn_x, trn_y,eval_set=[(val_x, val_y)],eval_metric='auc',early_stopping_rounds=100,verbose=100)
    print('Start predicting...')
    oof_xgb[test_in] = clf.predict(X_test)
    pre_xgb += clf.predict(test) / skf.n_splits
    
print('XGB predict over')

混合法(Blending)

基本思想:Blending采用了和stacking同样的方法,不过只从训练集中选择一个fold的结果,再和原始特征进行concat作为元学习器meta learner的特征,测试集上进行同样的操作。
把原始的训练集先分成两部分,比如70%的数据作为新的训练集,剩下30%的数据作为测试集。

  1. 第一层,我们在这70%的数据上训练多个模型,然后去预测那30%数据的label,同时也预测test集的label
  2. 在第二层,我们就直接用这30%数据在第一层预测的结果做为新特征继续训练,然后用test集第一层预测的label做特征,用第二层训练的模型做进一步预测

Blending与 Stacking的对比:
优点:

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

缺点:

  1. blending使用了很少的数据(第二阶段的blender只使用training set10%的量),blender可能会过拟合
  2. stacking使用多次的交叉验证会比较稳健
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/qq_43240913/article/details/110822100