模型融合与超参数优化

简介: 模型融合与超参数优化

模型融合


一般来说,通过融合多个不同的模型,可能提升机器学习的性能,这一方法在各种机器学习比赛中广泛应用, 常见的集成学习&模型融合方法包括:简单的Voting/Averaging(分别对于分类和回归问题)、Stacking、Boosting和Bagging。


1 Voting

模型融合其实也没有想象的那么高大上,从最简单的Voting说起,这也可以说是一种模型融合。假设对于一个二分类问题,有3个基础模型,那么就采取投票制的方法,投票多者确定为最终的分类。


2 Averaging

对于回归问题,一个简单直接的思路是取平均。稍稍改进的方法是进行加权平均。

权值可以用排序的方法确定,举个例子,比如A、B、C三种基本模型,模型效果进行排名,假设排名分别是1,2,3,那么给这三个模型赋予的权值分别是3/6、2/6、1/6。


注意两个问题

  • 如果进行投票的模型越多,那么显然其结果将会更好。但是其前提条件是模型之间相互独立,结果之间没有相关性。越相近的模型进行融合,融合效果也会越差。 模型之间差异越大,融合所得的结果将会更好。这种特性不会受融合方式的影响。注意这里所指模型之间的差异,并不是指正确率的差异,而是指模型之间相关性的差异。对于回归问题,对各种模型的预测结果进行平均,所得到的结果通过能够减少过拟合,并使得边界更加平滑,单个模型的边界可能很粗糙。
  • 在上述融合方法的基础上,一个进行改良的方式是对各个投票者/平均者分配不同的权重以改变其对最终结果影响的大小。对于正确率低的模型给予更低的权重,而正确率更高的模型给予更高的权重。


3 Bagging

Bagging就是采用有放回的方式进行抽样,用抽样的样本建立子模型,对子模型进行训练,这个过程重复多次,最后进行融合。大概分为这样两步:

  1. 重复K次
    有放回地重复抽样建模
    训练子模型
  2. 模型融合
    分类问题:voting
    回归问题:average

Bagging算法不用我们自己实现,随机森林就是基于Bagging算法的一个典型例子,采用的基分类器是决策树。


4 Boosting

Bagging算法可以并行处理,而Boosting的思想是一种迭代的方法,每一次训练的时候都更加关心分类错误的样例,给这些分类错误的样例增加更大的权重,下一次迭代的目标就是能够更容易辨别出上一轮分类错误的样例。最终将这些弱分类器进行加权相加。

其基本工作机制如下:

1、从初始样本集中训练出一个基学习器;
    2、根据基学习器的表现对样本集分布进行调整,使得做错的样本能在之后的过程中受到更多的关注;
    3、用调整后的样本集训练下一个基学习器;
    4、重复上述步骤,直到满足一定条件。


34.png


注意,一般只有弱分类器都是同一种分类器(即同质集成)的时候,才将弱分类器称为基学习器,如果是异质集成,则称之为个体学习器。由于不是本文重点,所以此处不作区分。特此说明。

最终将这些弱分类器进行加权相加。


35.png


常见的Boosting方法有Adaboost、GBDT、XGBOOST等


5 Stacking 算法


1、首先我们将训练集分为五份。

2、对于每一个基模型来说,我们用其中的四份来训练,然后对未用来的训练的一份训练集和测试集进行预测。然后改变所选的用来训练的训练集和用来验证的训练集,重复此步骤,直到获得完整的训练集的预测结果。

3、对五个模型,分别进行步骤2,我们将获得5个模型,以及五个模型分别通过交叉验证获得的训练集预测结果。即P1、P2、P3、P4、P5。

4、用五个模型分别对测试集进行预测,得到测试集的预测结果:T1、T2、T3、T4、T5。

5、将P15、T15作为下一层的训练集和测试集。在图中分别作为了模型6的训练集和测试集。


36.png


代码实例如下:

""" 
@author: quincy qiang 
@license: Apache Licence 
@file: 04_stakcing_template.py 
@time: 2019/12/12
@software: PyCharm 
"""
import numpy as np
import pandas as pd
import lightgbm as lgb
import xgboost as xgb
from sklearn.linear_model import BayesianRidge
from sklearn.model_selection import KFold, RepeatedKFold
from sklearn.preprocessing import OneHotEncoder, LabelEncoder
from scipy import sparse
import warnings
import time
import sys
import os
import re
import datetime
import matplotlib.pyplot as plt
import seaborn as sns
import plotly.offline as py
py.init_notebook_mode(connected=True)
import plotly.graph_objs as go
import plotly.tools as tls
from sklearn.metrics import mean_squared_error
from sklearn.metrics import log_loss
from gen_feas import load_data
train, test, no_features, features = load_data()
X_train = train[features].values
y_train = train['target']
target = y_train
X_test = test[features].values
## lgb
param = {
    'boosting_type': 'gbdt',
    'objective': 'binary',
    'metric': {'auc'},
    'max_depth': 4,
    'min_child_weight': 6,
    'num_leaves': 16,
    'learning_rate': 0.02,  # 0.05
    'feature_fraction': 0.7,
    'bagging_fraction': 0.7,
    'bagging_freq': 5,
    'verbose': -1
}
folds = KFold(n_splits=5, shuffle=True, random_state=2018)
oof_lgb = np.zeros(len(train))
predictions_lgb = np.zeros(len(test))
for fold_, (trn_idx, val_idx) in enumerate(folds.split(X_train, y_train)):
    print("fold n°{}".format(fold_ + 1))
    trn_data = lgb.Dataset(X_train[trn_idx], y_train[trn_idx])
    val_data = lgb.Dataset(X_train[val_idx], y_train[val_idx])
    num_round = 10000
    clf = lgb.train(param, trn_data, num_round, valid_sets=[trn_data, val_data], verbose_eval=200,
                    early_stopping_rounds=100)
    oof_lgb[val_idx] = clf.predict(X_train[val_idx], num_iteration=clf.best_iteration)
    predictions_lgb += clf.predict(X_test, num_iteration=clf.best_iteration) / folds.n_splits
print("CV score: {:<8.8f}".format(mean_squared_error(oof_lgb, target)))
#### xgb
xgb_params = {'booster': 'gbtree', 'objective': 'binary:logistic', 'eta': 0.02, 'max_depth': 4, 'min_child_weight': 6,
              'colsample_bytree': 0.7, 'subsample': 0.7, 'silent': 1, 'eval_metric': ['auc']}
folds = KFold(n_splits=5, shuffle=True, random_state=2018)
oof_xgb = np.zeros(len(train))
predictions_xgb = np.zeros(len(test))
for fold_, (trn_idx, val_idx) in enumerate(folds.split(X_train, y_train)):
    print("fold n°{}".format(fold_ + 1))
    trn_data = xgb.DMatrix(X_train[trn_idx], y_train[trn_idx])
    val_data = xgb.DMatrix(X_train[val_idx], y_train[val_idx])
    watchlist = [(trn_data, 'train'), (val_data, 'valid_data')]
    clf = xgb.train(dtrain=trn_data, num_boost_round=20000, evals=watchlist, early_stopping_rounds=200,
                    verbose_eval=100, params=xgb_params)
    oof_xgb[val_idx] = clf.predict(xgb.DMatrix(X_train[val_idx]), ntree_limit=clf.best_ntree_limit)
    predictions_xgb += clf.predict(xgb.DMatrix(X_test), ntree_limit=clf.best_ntree_limit) / folds.n_splits
print("CV score: {:<8.8f}".format(mean_squared_error(oof_xgb, target)))
# 将lgb和xgb的结果进行stacking
train_stack = np.vstack([oof_lgb, oof_xgb]).transpose()
test_stack = np.vstack([predictions_lgb, predictions_xgb]).transpose()
folds_stack = RepeatedKFold(n_splits=5, n_repeats=2, random_state=4590)
oof_stack = np.zeros(train_stack.shape[0])
predictions = np.zeros(test_stack.shape[0])
for fold_, (trn_idx, val_idx) in enumerate(folds_stack.split(train_stack, target)):
    print("fold {}".format(fold_))
    trn_data, trn_y = train_stack[trn_idx], target.iloc[trn_idx].values
    val_data, val_y = train_stack[val_idx], target.iloc[val_idx].values
    clf_3 = BayesianRidge()
    clf_3.fit(trn_data, trn_y)
    oof_stack[val_idx] = clf_3.predict(val_data)
    predictions += clf_3.predict(test_stack) / 10
mean_squared_error(target.values, oof_stack)
from pandas import DataFrame
result = DataFrame()
result['id'] = test['id']
result['target'] = predictions
result.to_csv('result/stacking.csv', index=False, sep=",", float_format='%.6f')


6 Blending


第一步:将原始训练数据划分为训练集和验证集。

第二步:使用训练集对训练T个不同的模型。

第三步:使用T个基模型,对验证集进行预测,结果作为新的训练数据。

第四步:使用新的训练数据,训练一个元模型。

第五步:使用T个基模型,对测试数据进行预测,结果作为新的测试数据。

第六步:使用元模型对新的测试数据进行预测,得到最终结果。


37.png


超参数优化


推荐两个工具:Optuna和BayesianOptimization


推荐1:Optuna

import numpy as np
import optuna
import lightgbm as lgb
import sklearn.datasets
import sklearn.metrics
from sklearn.model_selection import train_test_split
# FYI: Objective functions can take additional arguments
# (https://optuna.readthedocs.io/en/stable/faq.html#objective-func-additional-args).
def objective(trial):
    data, target = sklearn.datasets.load_breast_cancer(return_X_y=True)
    train_x, valid_x, train_y, valid_y = train_test_split(data, target, test_size=0.25)
    dtrain = lgb.Dataset(train_x, label=train_y)
    param = {
        "objective": "binary",
        "metric": "binary_logloss",
        "verbosity": -1,
        "boosting_type": "gbdt",
        "lambda_l1": trial.suggest_float("lambda_l1", 1e-8, 10.0, log=True),
        "lambda_l2": trial.suggest_float("lambda_l2", 1e-8, 10.0, log=True),
        "num_leaves": trial.suggest_int("num_leaves", 2, 256),
        "feature_fraction": trial.suggest_float("feature_fraction", 0.4, 1.0),
        "bagging_fraction": trial.suggest_float("bagging_fraction", 0.4, 1.0),
        "bagging_freq": trial.suggest_int("bagging_freq", 1, 7),
        "min_child_samples": trial.suggest_int("min_child_samples", 5, 100),
    }
    gbm = lgb.train(param, dtrain)
    preds = gbm.predict(valid_x)
    pred_labels = np.rint(preds)
    accuracy = sklearn.metrics.accuracy_score(valid_y, pred_labels)
    return accuracy
if __name__ == "__main__":
    study = optuna.create_study(direction="maximize")
    study.optimize(objective, n_trials=100)
    print("Number of finished trials: {}".format(len(study.trials)))
    print("Best trial:")
    trial = study.best_trial
    print("  Value: {}".format(trial.value))
    print("  Params: ")
    for key, value in trial.params.items():
        print("    {}: {}".format(key, value))


推荐2 BayesianOptimization


数据来源:https://www.kaggle.com/c/home-credit-default-risk


import pandas as pd
import numpy as np
import warnings
import time
warnings.filterwarnings("ignore")
import lightgbm as lgb
from bayes_opt import BayesianOptimization
from sklearn.metrics import roc_auc_score
application_train = pd.read_csv('../input/application_train.csv')
from sklearn.preprocessing import LabelEncoder
def label_encoder(input_df, encoder_dict=None):
    """ Process a dataframe into a form useable by LightGBM """
    # Label encode categoricals
    categorical_feats = input_df.columns[input_df.dtypes == 'object']
    for feat in categorical_feats:
        encoder = LabelEncoder()
        input_df[feat] = encoder.fit_transform(input_df[feat].fillna('NULL'))
    return input_df, categorical_feats.tolist(), encoder_dict
application_train, categorical_feats, encoder_dict = label_encoder(application_train)
X = application_train.drop('TARGET', axis=1)
y = application_train.TARGET
# 第一步:设置需要优化的参数
def lgb_eval(num_leaves, feature_fraction, bagging_fraction, max_depth, lambda_l1, lambda_l2, min_split_gain, min_child_weight):
    params = {'application':'binary','num_iterations':4000, 'learning_rate':0.05, 'early_stopping_round':100, 'metric':'auc'}
    params["num_leaves"] = round(num_leaves)
    params['feature_fraction'] = max(min(feature_fraction, 1), 0)
    params['bagging_fraction'] = max(min(bagging_fraction, 1), 0)
    params['max_depth'] = round(max_depth)
    params['lambda_l1'] = max(lambda_l1, 0)
    params['lambda_l2'] = max(lambda_l2, 0)
    params['min_split_gain'] = min_split_gain
    params['min_child_weight'] = min_child_weight
    cv_result = lgb.cv(params, train_data, nfold=n_folds, seed=random_seed, stratified=True, verbose_eval =200, metrics=['auc'])
    return max(cv_result['auc-mean'])
# 第二步:设置超参数搜索范围
lgbBO = BayesianOptimization(lgb_eval, {'num_leaves': (24, 45),
                                        'feature_fraction': (0.1, 0.9),
                                        'bagging_fraction': (0.8, 1),
                                        'max_depth': (5, 8.99),
                                        'lambda_l1': (0, 5),
                                        'lambda_l2': (0, 3),
                                        'min_split_gain': (0.001, 0.1),
                                        'min_child_weight': (5, 50)}, random_state=0)
# 第三步:设置优化目标
# lgbBO.maximize(init_points=init_round, n_iter=opt_round)
# 第四步:获取最优参数
# lgbBO.res['max']['max_params']


参考资料


相关文章
|
机器学习/深度学习 JSON 数据格式
CatBoost模型部署与在线预测教程
CatBoost模型部署与在线预测教程【2月更文挑战第16天】
545 2
|
关系型数据库 MySQL 数据库
百度搜索:蓝易云【【Docker】Docker部署Mysql并设置数据持久化教程】
通过以上步骤,您已经成功地在Docker中部署了MySQL,并设置了数据持久化,确保数据在容器重新启动或迁移时得以保留。
294 0
|
存储 监控 搜索推荐
【业务架构】业务驱动的推荐系统相关技术总结
【业务架构】业务驱动的推荐系统相关技术总结
317 0
|
存储 关系型数据库 MySQL
|
机器学习/深度学习 自然语言处理 搜索推荐
为什么说多模态是推荐系统破局的关键?来自饿了么一线的实战复盘
推荐系统作为互联网时代连接用户与信息的核心技术,正在经历从传统协同过滤向多模态智能推荐的重要变革。随着深度学习技术的快速发展,特别是大语言模型和多模态预训练技术的成熟,推荐系统开始从单纯依赖用户行为ID特征转向充分利用商品图像、文本描述等丰富内容信息的新范式。
332 18
|
Prometheus Cloud Native 数据挖掘
搭建数据分析系统 Grafana 详细指南
搭建Grafana数据分析系统涉及安装Docker和拉取Grafana容器,然后配置Prometheus数据源,创建仪表盘和面板,以及设置告警规则。利用Grafana的可视化功能,可以将数据直观展示并进行监控。系统还支持导入导出仪表盘,便于协作和管理。
|
12月前
|
机器学习/深度学习 人工智能 搜索推荐
AI音色克隆能模拟人的特质吗
AI技术迅猛发展,从文生文到文生视频,不断重塑生活与娱乐模式。音色克隆技术作为革命性成果,能精准捕捉并复制个人声音特征,应用于动画配音、游戏语音、音乐创作及教育领域,极大提升用户体验和内容创作效率。对于播客而言,这既是挑战也是机遇,借助该技术可提升作品趣味性和丰富度,提高创作效率,吸引更多流量。未来,AI音色克隆技术将在更多领域发挥重要作用。
|
存储 负载均衡 定位技术
现代数据库系统中的数据分片策略与优化
数据分片在现代数据库系统中扮演着关键角色,特别是在面对海量数据和高并发访问的情况下。本文探讨了数据分片的基本概念、常见的分片策略(如水平分片与垂直分片)、以及如何通过优化和选择合适的分片策略来提升数据库系统的性能和可扩展性。
|
计算机视觉 网络架构
CVPR 2024:基于MoE的通用图像融合模型,添加2.8%参数完成多项任务
【5月更文挑战第9天】CVPR 2024上的TC-MoA模型通过MoE策略改进通用图像融合,添加少量参数实现多任务处理。该模型使用适配器共享和相互信息正则化提升跨任务兼容性,动态路由网络适应不同任务需求。实验显示其在多模态、多曝光和多聚焦融合中表现出色,但依赖预训练基础模型且可能无法完全捕捉所有任务特定信息。[[arxiv.org/abs/2403.12494](https://arxiv.org/abs/2403.12494)]
507 1