自动化机器学习(AutoML)之自动贝叶斯调参
一、Python实现自动贝叶斯调整超参数
【导读】机器学习中,调参是一项繁琐但至关重要的任务,因为它很大程度上影响了算法的性能。手动调参十分耗时,网格和随机搜索不需要人力,但需要很长的运行时间。因此,诞生了许多自动调整超参数的方法。贝叶斯优化是一种用模型找到函数最小值方法,已经应用于机器学习问题中的超参数搜索,这种方法性能好,同时比随机搜索省时。此外,现在有许多Python库可以实现贝叶斯超参数调整。本文将使用Hyperopt库演示梯度提升机(Gradient Boosting Machine,GBM) 的贝叶斯超参数调整的完整示例。文章由贝叶斯优化方法、优化问题的四个部分、目标函数、域空间、优化过程、及结果展示几个部分组成。
贝叶斯优化方法
Python中的选择
优化问题的四个部分
目标函数:我们想要最小化的内容,在这里,目标函数是机器学习模型使用该组超参数在验证集上的损失。
域空间:要搜索的超参数的取值范围
优化算法:构造替代函数并选择下一个超参数值进行评估的方法。
结果历史记录:来自目标函数评估的存储结果,包括超参数和验证集上的损失。
数据集
梯度提升模型
目标函数
目标函数是需要我们最小化的。 它的输入为一组超参数,输出需要最小化的值(交叉验证损失)。Hyperopt将目标函数视为黑盒,只考虑它的输入和输出。 在这里,目标函数定义为:
def objective(hyperparameters):'''Returns validation score from hyperparameters'''model = Classifier(hyperparameters)validation_loss = cross_validation(model, training_data)return validation_loss
我们评估的是超参数在验证集上的表现,但我们不将数据集划分成固定的验证集和训练集,而是使用K折交叉验证。使用10倍交叉验证和提前停止的梯度提升机的完整目标函数如下所示。
import lightgbm as lgb
from hyperopt import STATUS_OKN_FOLDS = 10# Create the dataset
train_set = lgb.Dataset(train_features, train_labels)def objective(params, n_folds=N_FOLDS):'''Objective function for Gradient Boosting Machine Hyperparameter Tuning'''# Perform n_fold cross validation with hyperparameters# Use early stopping and evalute based on ROC AUCcv_results = lgb.cv(params, train_set, nfold=n_folds, num_boost_round=10000,early_stopping_rounds=100, metrics='auc', seed=50)# Extract the best scorebest_score = max(cv_results['auc-mean'])# Loss must be minimizedloss = 1 - best_score# Dictionary with information for evaluationreturn {'loss': loss, 'params': params, 'status': STATUS_OK}
关键点是cvresults = lgb.cv(...)
。为了实现提前停止的交叉验证,我们使用LightGBM函数cv,它输入为超参数,训练集,用于交叉验证的折数等。我们将迭代次数(numboostround)
设置为10000,但实际上不会达到这个数字,因为我们使用earlystopping_rounds
来停止训练,当连续100轮迭代效果都没有提升时,则提前停止,并选择模型。因此,迭代次数并不是我们需要设置的超参数。
一旦交叉验证完成,我们就会得到最好的分数(ROC AUC),然后,因为我们最小化目标函数,所以计算1- ROC AUC,然后返回这个值。
域空间
import lgb
# Default gradient boosting machine classifier
model = lgb.LGBMClassifier()
model
LGBMClassifier(boosting_type='gbdt', n_estimators=100,class_weight=None, colsample_bytree=1.0,learning_rate=0.1, max_depth=-1, min_child_samples=20,min_child_weight=0.001, min_split_gain=0.0, n_jobs=-1, num_leaves=31, objective=None, random_state=None, reg_alpha=0.0, reg_lambda=0.0, silent=True, subsample=1.0, subsample_for_bin=200000, subsample_freq=1)
其中一些我们不需要调整(例如objective和randomstate),我们将使用提前停止来找到最好的n_estimators。 但是,我们还有10个超参数要优化! 首次调整模型时,我通常会创建一个以默认值为中心的宽域空间,然后在后续搜索中对其进行细化。
例如,让我们在Hyperopt中定义一个简单的域,这是GBM中每棵树中叶子数量的离散均匀分布:
from hyperopt import hp
# Discrete uniform distribution
num_leaves = {'num_leaves': hp.quniform('num_leaves', 30, 150, 1)}
这里选择离散的均匀分布,因为叶子的数量必须是整数(离散),并且域中的每个值都可能(均匀)。
另一种分布选择是对数均匀,它在对数标度上均匀分布值。 我们将使用对数统一(从0.005到0.2)来获得学习率,因为它在几个数量级上变化:
# Learning rate log uniform distribution
learning_rate = {'learning_rate': hp.loguniform('learning_rate',np.log(0.005),np.log(0.2)}
下面分别绘制了均匀分布和对数均匀分布的图。 这些是核密度估计图,因此y轴是密度而不是计数!
现在,让我们定义整个域:
# Define the search space
space = {'class_weight': hp.choice('class_weight', [None, 'balanced']),'boosting_type': hp.choice('boosting_type', [{'boosting_type': 'gbdt', 'subsample': hp.uniform('gdbt_subsample', 0.5, 1)}, {'boosting_type': 'dart', 'subsample': hp.uniform('dart_subsample', 0.5, 1)},{'boosting_type': 'goss'}]),'num_leaves': hp.quniform('num_leaves', 30, 150, 1),'learning_rate': hp.loguniform('learning_rate', np.log(0.01), np.log(0.2)),'subsample_for_bin': hp.quniform('subsample_for_bin', 20000, 300000, 20000),'min_child_samples': hp.quniform('min_child_samples', 20, 500, 5),'reg_alpha': hp.uniform('reg_alpha', 0.0, 1.0),'reg_lambda': hp.uniform('reg_lambda', 0.0, 1.0),'colsample_bytree': hp.uniform('colsample_by_tree', 0.6, 1.0)
}
这里我们使用了许多不同的域分发类型:
choice:类别变量
quniform:离散均匀(整数间隔均匀)
uniform:连续均匀(间隔为一个浮点数)
loguniform:连续对数均匀(对数下均匀分布)
# boosting type domain
boosting_type = {'boosting_type': hp.choice('boosting_type', [{'boosting_type': 'gbdt', 'subsample': hp.uniform('subsample', 0.5, 1)}, {'boosting_type': 'dart', 'subsample': hp.uniform('subsample', 0.5, 1)},{'boosting_type': 'goss','subsample': 1.0}])}
这里我们使用条件域,这意味着一个超参数的值取决于另一个超参数的值。 对于提升类型“goss”,gbm不能使用子采样(仅选择训练观察的子样本部分以在每次迭代时使用)。 因此,如果提升类型是“goss”,则子采样率设置为1.0(无子采样),否则为0.5-1.0。 这是使用嵌套域实现的
定义域空间之后,我们可以从中采样查看样本。
# Sample from the full space
example = sample(space)# Dictionary get method with default
subsample = example['boosting_type'].get('subsample', 1.0)# Assign top-level keys
example['boosting_type'] = example['boosting_type']['boosting_type']
example['subsample'] = subsampleexample
{'boosting_type': 'gbdt',
'class_weight': 'balanced',
'colsample_bytree': 0.8111305579351727,
'learning_rate': 0.16186471096789776,
'min_child_samples': 470.0,
'num_leaves': 88.0,
'reg_alpha': 0.6338327001528129,
'reg_lambda': 0.8554826167886239,
'subsample_for_bin': 280000.0,
'subsample': 0.6318665053932255}
优化算法
虽然这是贝叶斯优化中概念上最难的部分,但在Hyperopt中创建优化算法只需一行。 要使用Tree Parzen Estimator,代码为:
from hyperopt import tpe
# Algorithm
tpe_algorithm = tpe.suggest
在优化时,TPE算法根据过去的结果构建概率模型,并通过最大化预期的改进来决定下一组超参数以在目标函数中进行评估。
结果历史
from hyperopt import Trials
# Trials object to track progress
bayes_trials = Trials()
为了监控训练运行进度,可以将结果历史写入csv文件,防止程序意外中断导致评估结果消失。
import csv# File to save first results
out_file = 'gbm_trials.csv'
of_connection = open(out_file, 'w')
writer = csv.writer(of_connection)# Write the headers to the file
writer.writerow(['loss', 'params', 'iteration', 'estimators', 'train_time'])
of_connection.close()
然后在目标函数中我们可以在每次迭代时添加行写入csv:
# Write to the csv file ('a' means append)
of_connection = open(out_file, 'a')
writer = csv.writer(of_connection)
writer.writerow([loss, params, iteration, n_estimators, run_time])
of_connection.close()
优化:
from hyperopt import fmin
MAX_EVALS = 500
# Optimize
best = fmin(fn = objective, space = space, algo = tpe.suggest, max_evals = MAX_EVALS, trials = bayes_trials)
在每次迭代时,算法从代理函数中选择新的超参数值,该代理函数基于先前的结果构建并在目标函数中评估这些值。 这继续用于目标函数的MAX_EVALS评估,其中代理函数随每个新结果不断更新。
结果:
从fmin返回的最佳对象包含在目标函数上产生最低损失的超参数:
{'boosting_type': 'gbdt','class_weight': 'balanced','colsample_bytree': 0.7125187075392453,'learning_rate': 0.022592570862044956,'min_child_samples': 250,'num_leaves': 49,'reg_alpha': 0.2035211643104735,'reg_lambda': 0.6455131715928091,'subsample': 0.983566228071919,'subsample_for_bin': 200000}
一旦我们有了这些超参数,我们就可以使用它们来训练完整训练数据的模型,然后评估测试数据。 最终结果如下:
The best model scores 0.72506 AUC ROC on the test set.
The best cross validation score was 0.77101 AUC ROC.
This was achieved after 413 search iterations.
作为参考,500次随机搜索迭代返回了一个模型,该模型在测试集上评分为0.7232 ROC AUC,在交叉验证中评分为0.76850。没有优化的默认模型在测试集上评分为0.7143 ROC AUC。
在查看结果时,请记住一些重要的注意事项:
最佳超参数是那些在交叉验证方面表现最佳的参数,而不一定是那些在测试数据上做得最好的参数。当我们使用交叉验证时,我们希望这些结果可以推广到测试数据。
即使使用10倍交叉验证,超参数调整也会过度拟合训练数据。交叉验证的最佳分数显著高于测试数据。
随机搜索可以通过纯粹的运气返回更好的超参数(重新运行笔记本可以改变结果)。贝叶斯优化不能保证找到更好的超参数,并且可能陷入目标函数的局部最小值。
另一个重点是超参数优化的效果将随数据集的不同而不同。相对较小的数据集(训练集大小为6000),调整超参数,最终得到的模型的提升并不大,但数据集更大时,效果会很明显。
因此,通过贝叶斯概率来优化超参数,我们可以:在测试集上得到更好的性能;调整超参数的迭代次数减少.
可视化结果:
绘制结果图表是一种直观的方式,可以了解超参数搜索过程中发生的情况。此外,通过将贝叶斯优化与随机搜索进行比较,可以看出方法的不同之处。
搜索的演变
继续搜索
如果我们对模型的性能不满意,我们可以继续使用Hyperopt进行搜索。我们只需要传入相同的试验对象,算法将继续搜索。
结论
可以使用贝叶斯优化来完成机器学习模型的超参数自动调整。与随机或网格搜索相比,贝叶斯优化对目标函数的评估较少,测试集上的更好的泛化性能。
自动化机器学习(AutoML)之自动贝叶斯调参相关推荐
- 机器学习调参——网格搜索调参,随机搜索调参,贝叶斯调参
from sklearn.datasets import load_boston from sklearn.metrics import mean_squared_error from lightgb ...
- 网格搜索、随机搜索和贝叶斯调参总结与实践
网格搜索 网格搜索时应用最广泛的超参数搜素算法,网格搜索通过查找搜索范围内的所有点,来确定最优值.一般是通过给出较大的搜索范围以及较小的步长,网格搜索时一定可以找到全局最大值或全局最小值的. 但是网格 ...
- 调参1——随机森林贝叶斯调参
贝叶斯调参教程请参考:https://blog.csdn.net/weixin_35757704/article/details/118480135 安装贝叶斯调参: pip install baye ...
- LGBM使用贝叶斯调参
贝叶斯调参的相关知识与代码格式请参考:https://blog.csdn.net/weixin_35757704/article/details/118416689 构造LGBM模型 model = ...
- 贝叶斯调参——bayes_opt
一.简介 贝叶斯调参主要思想是,给定优化的目标函数(广义的函数,只需指定输入和输出即可,无需知道内部结构以及数学性质),通过不断地添加样本点来更新目标函数的后验分布 他与常规的网格搜索或者随机搜索的区 ...
- python朴素贝叶斯调参_邹博机器学习升级版II附讲义、参考书与源码下载(数学 xgboost lda hmm svm)...
课程介绍 本课程特点是从数学层面推导最经典的机器学习算法,以及每种算法的示例和代码实现(Python).如何做算法的参数调试.以实际应用案例分析各种算法的选择等. 1.每个算法模块按照"原理 ...
- [机器学习]超参数优化---贝叶斯优化(Bayesian Optimization) 理解
背景 很多算法工程师戏谑自己是调参工程师,因为他们需要在繁杂的算法参数中找到最优的组合,往往在调参的过程中痛苦而漫长的度过一天.如果有一种方式可以帮助工程师找到最优的参数组合,那一定大有裨益,贝叶斯超 ...
- python贝叶斯优化算法_【干货】手把手教你Python实现自动贝叶斯调整超参数
[导读]机器学习中,调参是一项繁琐但至关重要的任务,因为它很大程度上影响了算法的性能.手动调参十分耗时,网格和随机搜索不需要人力,但需要很长的运行时间.因此,诞生了许多自动调整超参数的方法.贝叶斯优化 ...
- 机器学习面试题——朴素贝叶斯
机器学习面试题--朴素贝叶斯 提示:这些知识点也是大厂笔试经常考的题目,我记得阿里和京东就考!!!想必在互联网大厂就会用这些知识解决实际问题 朴素贝叶斯介绍一下 朴素贝叶斯优缺点 贝叶斯公式 朴素贝叶 ...
最新文章
- MATLAB【二】————图像做减法,批量文本处理,子图显示
- python ipython spyder
- python【蓝桥杯vip练习题库】ADV-308递归输出
- 谁来执行Rebalance以及管理consumer的group呢?
- CSS魔法堂:深入理解line-height和vertical-align
- Linux的实际操作:文件目录类的实用指令(重定向“>“和追加“>>“)
- AJAX框架衣柜内部布局,​最合理的衣柜内部布局解析,3大细节不容小觑
- java的数据连接_java中连接各种数据的方法
- html5怎么改为vue_是否还在疑惑Vue.js中组件的data为什么是函数类型而不是对象类型...
- oracle in table类型,Oracle Built-in Data Types(Oracle内置数据类型)
- qt qss设置字体大小_Qt编写输入法V2019终极版
- 人人开源中invalid Code
- Leetcode——最长公共子序列 / 最长公共子串
- 计算机ppt听课记录,怎样做好听课记录.ppt
- java 闰年闰月_闰年闰月查询表
- 项目总结:快餐店POS收银系统
- PXC pxc_strict_mode
- 【CF487E】Tourists
- 物体识别,Win7下运行TensorFlow Object Detection API详细版教程(零基础操作)
- 阿里大数据ACP认证对找工作到底有用嘛?
热门文章
- 递归循环一个无限极数组_理解递归、尾调用优化和蹦床函数优化
- java重写6,java重写equals()方法和hashCode()方法
- NSURLSessionDataTask与NSOperationQueue实现多文件断点下载(任意时刻终止进程,重启应用,自动重启下载)...
- nginx brotli 压缩试用
- Python time.time()方法
- 仿网易云音乐客户端的底部播放器的实现思路
- 快速部署Enterprise Manager Cloud Control 12c(12.1) Agent
- Asp.net MVC 仿照博客园的简单网站首页 列表设计
- 基于Vue-cli和Vux的webpack配置
- 计算机基本网络测试命令实验报告,实验三 基本网络测试工具的使用