模型融合与超参数优化

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

模型融合


一般来说,通过融合多个不同的模型,可能提升机器学习的性能,这一方法在各种机器学习比赛中广泛应用, 常见的集成学习&模型融合方法包括:简单的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']


参考资料


相关文章
|
7月前
|
数据采集 人工智能
论文介绍:训练计算最优的大型语言模型
【2月更文挑战第30天】研究人员发现,在有限计算资源下,优化大型语言模型的训练需使模型大小和训练数据量成比例增长,以达到计算最优。通过训练700亿参数的Chinchilla模型并对比GPT-3等,验证了该策略的有效性。论文强调数据集质量和伦理隐私问题,并提出预测模型扩展的方法。这一发现对AI领域的模型训练策略提供了新思路,但也面临数据质量和伦理挑战。
76 2
论文介绍:训练计算最优的大型语言模型
|
7月前
|
物联网 网络架构
PHATGOOSE:使用LoRA Experts创建低成本混合专家模型实现零样本泛化
这篇2月的新论文介绍了Post-Hoc Adaptive Tokenwise Gating Over an Ocean of Specialized Experts (PHATGOOSE),这是一种通过利用一组专门的PEFT模块(如LoRA)实现零样本泛化的新方法
88 0
|
4天前
|
机器学习/深度学习 算法 数据可视化
基于深度混合架构的智能量化交易系统研究: 融合SSDA与LSTM自编码器的特征提取与决策优化方法
本文探讨了在量化交易中结合时序特征和静态特征的混合建模方法。通过整合堆叠稀疏降噪自编码器(SSDA)和基于LSTM的自编码器(LSTM-AE),构建了一个能够全面捕捉市场动态特性的交易系统。SSDA通过降噪技术提取股票数据的鲁棒表示,LSTM-AE则专注于捕捉市场的时序依赖关系。系统采用A2C算法进行强化学习,通过多维度的奖励计算机制,实现了在可接受的风险水平下最大化收益的目标。实验结果显示,该系统在不同波动特征的股票上表现出差异化的适应能力,特别是在存在明确市场趋势的情况下,决策准确性较高。
21 5
基于深度混合架构的智能量化交易系统研究: 融合SSDA与LSTM自编码器的特征提取与决策优化方法
|
3天前
|
机器学习/深度学习 存储 自然语言处理
如何提升大模型的“深度思维能力”
本文探讨了如何通过模拟人类的思维过程来提升大模型的推理和规划能力。文章从人类的思维模式入手,分析了人类在面对复杂问题时的“增-减”信息循环,提出了通过增加相关信息和减少噪声来降低信息熵的方法。文章还讨论了如何生成逻辑自洽的推理路径,并通过实例说明了多结论问题的处理方法。最后,文章指出,通过现有的大模型进行针对性微调,可以逐步强化数据,提升模型的推理和规划能力。
|
11天前
|
机器学习/深度学习 存储 人工智能
《智领未来:C++ 与遗传算法在 AI 模型参数优化中的深度融合》
本文探讨了在C++中实现遗传算法并应用于人工智能模型参数优化的方法。遗传算法模拟自然界的进化过程,通过选择、交叉和变异等操作优化模型参数。文章详细介绍了C++实现遗传算法的关键步骤,包括定义个体与种群、初始化种群、适应度评估、选择、交叉、变异及迭代更新种群。此外,还讨论了C++实现遗传算法的优势与挑战,并展望了其在深度学习、强化学习、边缘计算等领域的应用前景。
45 9
|
2月前
|
人工智能
采用8个64B模型进行的模型融合,效果如何呢?
【10月更文挑战第1天】论文解读:针对模型融合(Model Merging)中的AI模型数量、模型大小、模型能力、合并方法等因素的实验及结果
49 2
|
7月前
|
人工智能 算法 测试技术
论文介绍:进化算法优化模型融合策略
【5月更文挑战第3天】《进化算法优化模型融合策略》论文提出使用进化算法自动化创建和优化大型语言模型,通过模型融合提升性能并减少资源消耗。实验显示,这种方法在多种基准测试中取得先进性能,尤其在无特定任务训练情况下仍能超越参数更多模型。同时,该技术成功应用于创建具有文化意识的日语视觉-语言模型。然而,模型融合可能产生逻辑不连贯响应和准确性问题,未来工作将聚焦于图像扩散模型、自动源模型选择及生成自我改进的模型群体。[论文链接: https://arxiv.org/pdf/2403.13187.pdf]
182 1
|
7月前
|
机器学习/深度学习 Python
超参数优化:提升机器学习模型性能
【5月更文挑战第31天】超参数优化对提升机器学习模型性能至关重要。网格搜索和随机搜索是常见方法,Python示例展示了如何使用GridSearchCV进行网格搜索。其他高级技术包括基于梯度的优化和贝叶斯优化。优化时注意选择合适评估指标、划分训练验证集,并进行迭代调整。自动化工具可简化这一过程。超参数优化是一个持续演进的领域,对于构建高性能模型具有关键作用。
114 0
|
7月前
|
机器学习/深度学习 存储 自然语言处理
深度探索自适应学习率调整:从传统方法到深度学习优化器
【5月更文挑战第15天】 在深度学习的复杂网络结构与海量数据中,学习率作为模型训练的关键超参数,其调整策略直接影响着模型的收敛速度与最终性能。传统的学习率调整方法,如固定学习率、学习率衰减等,虽然简单易行,但在多样化的任务面前往往显得力不从心。近年来,随着自适应学习率技术的兴起,一系列创新的优化器如Adam、RMSProp和Adagrad等应运而生,它们通过引入自适应机制动态调整学习率,显著改善了模型的训练效率与泛化能力。本文将深入剖析传统学习率调整方法的原理与局限性,并详细介绍当前主流的自适应学习率优化器,最后探讨未来可能的发展方向。
|
7月前
|
机器学习/深度学习 Python
探索XGBoost:深度集成与迁移学习
探索XGBoost:深度集成与迁移学习
239 2