贝叶斯全局优化(LightGBM调参)

GridSearchCV调参-----------------太慢,效果也不好
这里结合Kaggle比赛的一个数据集,记录一下使用贝叶斯全局优化和高斯过程来寻找最佳参数的方法步骤。

1.安装贝叶斯全局优化库

从pip安装最新版本

pip install bayesian-optimization

2.加载数据集

import pandas as pd
import numpy as np
from sklearn.model_selection import StratifiedKFold
from scipy.stats import rankdata
from sklearn import metrics
import lightgbm as lgb
import warnings
import gc
pd.set_option('display.max_columns', 200)
train_df = pd.read_csv('../input/train.csv')
test_df = pd.read_csv('../input/test.csv')

目标变量的分布

target = 'target'
predictors = train_df.columns.values.tolist()[2:]
train_df.target.value_counts()

在这里插入图片描述
问题是不平衡。这里使用50%分层行作为保持行,以便验证集获得最佳参数。 稍后将在最终模型拟合中使用5折交叉验证。

bayesian_tr_index, bayesian_val_index  = list(StratifiedKFold(n_splits=2, 
shuffle=True, random_state=1).split(train_df, train_df.target.values))[0]

这些bayesian_tr_index和bayesian_val_index索引将用于贝叶斯优化,作为训练和验证数据集的索引。

3.黑盒函数优化(LightGBM)

在加载数据时,为LightGBM创建黑盒函数以查找参数。

def LGB_bayesian(
    num_leaves,  # int
    min_data_in_leaf,  # int
    learning_rate,
    min_sum_hessian_in_leaf,    # int  
    feature_fraction,
    lambda_l1,
    lambda_l2,
    min_gain_to_split,
    max_depth):
    
    # LightGBM expects next three parameters need to be integer. So we make them integer
    num_leaves = int(num_leaves)
    min_data_in_leaf = int(min_data_in_leaf)
    max_depth = int(max_depth)

    assert type(num_leaves) == int
    assert type(min_data_in_leaf) == int
    assert type(max_depth) == int

    param = {
        'num_leaves': num_leaves,
        'max_bin': 63,
        'min_data_in_leaf': min_data_in_leaf,
        'learning_rate': learning_rate,
        'min_sum_hessian_in_leaf': min_sum_hessian_in_leaf,
        'bagging_fraction': 1.0,
        'bagging_freq': 5,
        'feature_fraction': feature_fraction,
        'lambda_l1': lambda_l1,
        'lambda_l2': lambda_l2,
        'min_gain_to_split': min_gain_to_split,
        'max_depth': max_depth,
        'save_binary': True, 
        'seed': 1337,
        'feature_fraction_seed': 1337,
        'bagging_seed': 1337,
        'drop_seed': 1337,
        'data_random_seed': 1337,
        'objective': 'binary',
        'boosting_type': 'gbdt',
        'verbose': 1,
        'metric': 'auc',
        'is_unbalance': True,
        'boost_from_average': False,   

    }    
    
    
    xg_train = lgb.Dataset(train_df.iloc[bayesian_tr_index][predictors].values,
                           label=train_df.iloc[bayesian_tr_index][target].values,
                           feature_name=predictors,
                           free_raw_data = False
                           )
    xg_valid = lgb.Dataset(train_df.iloc[bayesian_val_index][predictors].values,
                           label=train_df.iloc[bayesian_val_index][target].values,
                           feature_name=predictors,
                           free_raw_data = False
                           )   

    num_round = 5000
    clf = lgb.train(param, xg_train, num_round, valid_sets = [xg_valid], verbose_eval=250, early_stopping_rounds = 50)
    
    predictions = clf.predict(train_df.iloc[bayesian_val_index][predictors].values, num_iteration=clf.best_iteration)   
    
    score = metrics.roc_auc_score(train_df.iloc[bayesian_val_index][target].values, predictions)
    
    return score

上面的LGB_bayesian函数将作为贝叶斯优化的黑盒函数。 我已经在LGB_bayesian函数中为LightGBM定义了trainng和validation数据集。

LGB_bayesian函数从贝叶斯优化框架获取num_leaves,min_data_in_leaf,learning_rate,min_sum_hessian_in_leaf,feature_fraction,lambda_l1,lambda_l2,min_gain_to_split,max_depth的值。 请记住,对于LightGBM,num_leaves,min_data_in_leaf和max_depth应该是整数。 但贝叶斯优化会发送连续的函数。 所以我强制它们是整数。 我只会找到它们的最佳参数值。 读者可以增加或减少要优化的参数数量。
现在需要为这些参数提供边界,以便贝叶斯优化仅在边界内搜索。

bounds_LGB = {
    'num_leaves': (5, 20), 
    'min_data_in_leaf': (5, 20),  
    'learning_rate': (0.01, 0.3),
    'min_sum_hessian_in_leaf': (0.00001, 0.01),    
    'feature_fraction': (0.05, 0.5),
    'lambda_l1': (0, 5.0), 
    'lambda_l2': (0, 5.0), 
    'min_gain_to_split': (0, 1.0),
    'max_depth':(3,15),
}

让我们将它们全部放在BayesianOptimization对象中

from bayes_opt import BayesianOptimization
LGB_BO = BayesianOptimization(LGB_bayesian, bounds_LGB, random_state=13)

现在,让我们来优化key space (parameters):

print(LGB_BO.space.keys)

在这里插入图片描述
我创建了BayesianOptimization对象(LGB_BO),在调用maxime之前它不会工作。在调用之前,解释一下贝叶斯优化对象(LGB_BO)的两个参数,我们可以传递给它们进行最大化:
init_points:我们想要执行的随机探索的初始随机运行次数。 在我们的例子中,LGB_bayesian将被运行n_iter次。
n_iter:运行init_points数后,我们要执行多少次贝叶斯优化运行。

现在,是时候从贝叶斯优化框架调用函数来最大化。 我允许LGB_BO对象运行5个init_points和5个n_iter。

init_points = 5
n_iter = 5
print('-' * 130)

with warnings.catch_warnings():
    warnings.filterwarnings('ignore')
    LGB_BO.maximize(init_points=init_points, n_iter=n_iter, acq='ucb', xi=0.0, alpha=1e-6)

在这里插入图片描述
优化完成后,让我们看看我们得到的最大值是多少。

LGB_BO.max['target']

在这里插入图片描述
参数的验证AUC是0.89, 让我们看看参数:

LGB_BO.max['params']

在这里插入图片描述
现在我们可以将这些参数用于我们的最终模型!

BayesianOptimization库中还有一个很酷的选项。 你可以探测LGB_bayesian函数,如果你对最佳参数有所了解,或者您从其他kernel获取参数。 我将在此复制并粘贴其他内核中的参数。 你可以按照以下方式进行探测:

LGB_BO.probe(
    params={'feature_fraction': 0.1403, 
            'lambda_l1': 4.218, 
            'lambda_l2': 1.734, 
            'learning_rate': 0.07, 
            'max_depth': 14, 
            'min_data_in_leaf': 17, 
            'min_gain_to_split': 0.1501, 
            'min_sum_hessian_in_leaf': 0.000446, 
            'num_leaves': 6},
    lazy=True, # 
)

好的,默认情况下这些将被懒惰地探索(lazy = True),这意味着只有在你下次调用maxime时才会评估这些点。 让我们对LGB_BO对象进行最大化调用。

LGB_BO.maximize(init_points=0, n_iter=0) # remember no init_points or n_iter

在这里插入图片描述
最后,通过属性LGB_BO.res可以获得探测的所有参数列表及其相应的目标值。

for i, res in enumerate(LGB_BO.res):
    print("Iteration {}: \n\t{}".format(i, res))

在这里插入图片描述
我们在调查中获得了更好的验证分数!和以前一样,我只运行LGB_BO 10次。在实践中,我将它增加到100。

LGB_BO.max['target']

在这里插入图片描述

LGB_BO.max['params']

在这里插入图片描述
让我们一起构建一个模型使用这些参数。

4.训练LightGBM模型

param_lgb = {
        'num_leaves': int(LGB_BO.max['params']['num_leaves']), # remember to int here
        'max_bin': 63,
        'min_data_in_leaf': int(LGB_BO.max['params']['min_data_in_leaf']), # remember to int here
        'learning_rate': LGB_BO.max['params']['learning_rate'],
        'min_sum_hessian_in_leaf': LGB_BO.max['params']['min_sum_hessian_in_leaf'],
        'bagging_fraction': 1.0, 
        'bagging_freq': 5, 
        'feature_fraction': LGB_BO.max['params']['feature_fraction'],
        'lambda_l1': LGB_BO.max['params']['lambda_l1'],
        'lambda_l2': LGB_BO.max['params']['lambda_l2'],
        'min_gain_to_split': LGB_BO.max['params']['min_gain_to_split'],
        'max_depth': int(LGB_BO.max['params']['max_depth']), # remember to int here
        'save_binary': True,
        'seed': 1337,
        'feature_fraction_seed': 1337,
        'bagging_seed': 1337,
        'drop_seed': 1337,
        'data_random_seed': 1337,
        'objective': 'binary',
        'boosting_type': 'gbdt',
        'verbose': 1,
        'metric': 'auc',
        'is_unbalance': True,
        'boost_from_average': False,
    }

如您所见,我将LGB_BO的最佳参数保存到param_lgb字典中,它们将用于训练5折的模型。
Kfolds数量:

nfold = 5
gc.collect()
skf = StratifiedKFold(n_splits=nfold, shuffle=True, random_state=2019)
oof = np.zeros(len(train_df))
predictions = np.zeros((len(test_df),nfold))

i = 1
for train_index, valid_index in skf.split(train_df, train_df.target.values):
    print("\nfold {}".format(i))
    xg_train = lgb.Dataset(train_df.iloc[train_index][predictors].values,
                           label=train_df.iloc[train_index][target].values,
                           feature_name=predictors,
                           free_raw_data = False
                           )
    xg_valid = lgb.Dataset(train_df.iloc[valid_index][predictors].values,
                           label=train_df.iloc[valid_index][target].values,
                           feature_name=predictors,
                           free_raw_data = False
                           )   

    
    clf = lgb.train(param_lgb, xg_train, 5000, valid_sets = [xg_valid], verbose_eval=250, early_stopping_rounds = 50)
    oof[valid_index] = clf.predict(train_df.iloc[valid_index][predictors].values, num_iteration=clf.best_iteration) 
    
    predictions[:,i-1] += clf.predict(test_df[predictors], num_iteration=clf.best_iteration)
    i = i + 1

print("\n\nCV AUC: {:<0.2f}".format(metrics.roc_auc_score(train_df.target.values, oof)))

在这里插入图片描述
所以我们在5折交叉验证中获得了0.90 AUC。
让我们对5折预测进行排名平均。

5.排名平均值

print("Rank averaging on", nfold, "fold predictions")
rank_predictions = np.zeros((predictions.shape[0],1))
for i in range(nfold):
    rank_predictions[:, 0] = np.add(rank_predictions[:, 0], rankdata(predictions[:, i].reshape(-1,1))/rank_predictions.shape[0]) 

rank_predictions /= nfold

6.提交

sub_df = pd.DataFrame({"ID_code": test_df.ID_code.values})
sub_df["target"] = rank_predictions
sub_df.to_csv("Customer_Transaction_rank_predictions.csv", index=False)
  • 11
    点赞
  • 59
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
贝叶斯优化是一种用于自动调参的方法,可以在给定的搜索空间内找到最优的超参数组合。LightGBM是一种基于梯度提升决策树(GBDT)的机器学习算法,它在处理大规模数据和高维特征时具有较快的训练速度和较低的内存消耗。现在,我将介绍如何使用贝叶斯优化来调整LightGBM模型的超参数。 首先,确定要调整的超参数。LightGBM有许多可调整的超参数,比如学习率(learning rate)、树的深度(max_depth)、叶子节点数(num_leaves)等等。你可以根据自己的需求选择需要调整的超参数。 然后,确定贝叶斯优化的目标函数。在这里,我们可以选择模型在验证集上的评估指标作为目标函数,比如准确率、AUC等等。目标函数应当与超参数相关,并且越大越好或者越小越好。 接下来,确定搜索空间。搜索空间包括每个超参数的取值范围。你可以选择在一定范围内均匀采样或者使用离散值进行采样。 然后,使用贝叶斯优化算法进行超参数搜索。常见的贝叶斯优化算法有高斯过程、树结构模型等。你可以使用现有的贝叶斯优化库,比如Hyperopt、Optuna等。 在每次迭代中,根据目标函数的反馈调整超参数的取值,并更新搜索空间。通过多次迭代,最终找到最优的超参数组合。 最后,使用找到的最优超参数重新训练LightGBM模型,并在测试集上评估模型的性能。 以上就是使用贝叶斯优化来调整LightGBM模型的步骤。希望对你有所帮助!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值