赞
踩
随着机器学习用来处理大量数据被广泛使用,超参数调优所需要的空间和过程越来越复杂。传统的网格搜索和随即搜索已经不能满足用户的需求,因此方便快捷的贝叶斯优化调参越来越受程序员青睐。
贝叶斯优化用于机器学习调参由J. Snoek(2012)提出,主要思想是,给定优化的目标函数(广义的函数,只需指定输入和输出即可,无需知道内部结构以及数学性质),通过不断地添加样本点来更新目标函数的后验分布(高斯过程,直到后验分布基本贴合于真实分布。简单的说,就是考虑了上一次参数的信息,从而更好的调整当前的参数。
贝叶斯优化有两个核心过程,先验函数(Prior Function,PF)与采集函数(Acquisition Function,AC),采集函数也可以叫效能函数(Utility Funtcion),但一般还是称呼为采集函数。PF主要利用高斯过程回归(也可以是其它PF函数,但高斯过程回归用的多);AC主要包括EI,PI,UCB这几种方法,同时exploration与exploitation的平衡,也是通过AC来完成的。
注:这里对高斯过程不做详细介绍。
常用的超参数调参的方法有:网格搜索,随机搜索与贝叶斯优化
网格搜索是应用最广泛的超参数搜索算法,网格搜索通过查找搜索范围内的所有的点,来确定最优值。一般通过给出较大的搜索范围以及较小的步长,网格搜索是一定可以找到全局最大值或最小值的。但是,网格搜索一个比较大的问题是,它十分消耗计算资源,特别是需要调优的超参数比较多的时候。(网格搜索就相当于穷举法)
与网格搜索相比,随机搜索并未尝试所有参数值,而是从指定的分布中采样固定数量的参数设置。它的理论依据是,如果随即样本点集足够大,那么也可以找到全局的最大或最小值,或它们的近似值。通过对搜索范围的随机取样,随机搜索一般会比网格搜索要快一些。但是和网格搜索的快速版(非自动版)相似,结果也是没法保证的。
区别:
贝叶斯调参有很多实现方法,其中python的包就有好几个,BayesianOptimization、bayesopt、skopt
本博客主要讲述一下Bayesian Optimiazation调参的方法,讲述一下python实现。其中,以随机森林的回归算法调参为例。随机森林的超参数请参考随机森林RF原理总结的RF调参一节。需要调试的参数为n_estimators、max_features、max_depth、min_samples_split。
首先安装bayesian-optimization。
pip install bayesian-optimization
安装包成功后,就可以写代码调参啦。本博客与其他贝叶斯调参的例子不同,按BayesianOptimization教程写,具有很好的复用性。先做一下前期准备:
from sklearn.ensemble import RandomForestRegressor
from bayes_opt import BayesianOptimization
看一下贝叶斯调参前的结果,
model = RandomForestRegressor()
model = model.fit(train_x, train_y)
score = model.score(test_x, test_y)
print('默认参数下测试集评分:')
print(score)
其中,train_x, train_y是训练集数据,test_x, test_y是测试集数据。
默认参数下测试集评分:
0.6822328326434381
然后进行贝叶斯调参,主要分为五个步骤,构造黑盒函数、确定域空间、实例化对象、确定迭代次数和搜索最优结果,下面就详细解释一下每一步。
首先构造黑盒函数,就是你要求最优的目标函数。按照默认的求的随机森林回归建模的测试集评分,同时也是预测结果的R_2score。因为bayes_opt库只支持最大值,所以最后的输出如果是求最小值,那么需要在前面加上负号,以转为最大值。由于bayes优化只能优化连续超参数,因此要加上int()转为离散超参数。
def black_box_function(n_estimators, min_samples_split, max_features, max_depth):
res = RandomForestRegressor(n_estimators=int(n_estimators),
min_samples_split=int(min_samples_split),
max_features=min(max_features, 0.999), # float
max_depth=int(max_depth),
random_state=2
).fit(train_x, train_y).score(test_x, test_y)
return res
黑盒函数即目标函数是加入需要调试的超参数后构建模型的测试集评分。
pbounds= {'n_estimators': (10, 250),
'min_samples_split': (2, 25),
'max_features': (0.1, 0.999),
'max_depth': (5, 15)}
将需要调试的超参数的取值范围确定,()两端表示取值范围。
optimizer = BayesianOptimization(
f=black_box_function,
pbounds=pbounds,
verbose=2, # verbose = 1 prints only when a maximum is observed, verbose = 0 is silent
random_state=1,
)
这一步就是在实例化贝叶斯优化的对象,第一个参数是黑盒函数即目标函数,第二个参数是调试的超参数的取值范围,第三个数是确定最大值是否唯一,第四个参数是一个随机数。
optimizer.maximize(
init_points=5, #执行随机搜索的步数
n_iter=25, #执行贝叶斯优化的步数
)
迭代次数由两部分组成,随机搜索的步数和贝叶斯优化的步数,贝叶斯优化的步数要多一点,步骤越多,就越有可能找到一个好的最大值。随机探索可以通过扩大探索空间而有所帮助。这里以迭代30次为例。
print(optimizer.max)
输出最优结果,就会把整个迭代的过程以及最优结果输出。如下:
| iter | target | max_depth | max_fe… | min_sa… | n_esti… |
| 1 | 0.6855 | 9.17 | 0.7476 | 2.003 | 82.56 |
| 2 | 0.6605 | 6.468 | 0.183 | 6.284 | 92.93 |
| 3 | 0.6913 | 8.968 | 0.5844 | 11.64 | 174.5 |
| 4 | 0.6812 | 7.045 | 0.8894 | 2.63 | 170.9 |
| 5 | 0.6904 | 9.173 | 0.6023 | 5.229 | 57.54 |
| 6 | 0.6944 | 8.415 | 0.3039 | 11.39 | 173.9 |
| 7 | 0.6677 | 5.224 | 0.8589 | 12.4 | 171.5 |
| 8 | 0.6511 | 8.95 | 0.1 | 9.111 | 173.8 |
| 9 | 0.6861 | 8.641 | 0.7845 | 12.19 | 173.1 |
| 10 | 0.6791 | 7.723 | 0.7519 | 5.867 | 57.67 |
| 11 | 0.6831 | 9.569 | 0.8303 | 4.038 | 56.8 |
| 12 | 0.6863 | 9.799 | 0.6507 | 6.444 | 56.32 |
| 13 | 0.686 | 10.57 | 0.7219 | 6.846 | 58.33 |
| 14 | 0.6365 | 7.673 | 0.1 | 12.26 | 174.6 |
| 15 | 0.6843 | 9.719 | 0.8212 | 6.935 | 56.0 |
| 16 | 0.6917 | 9.34 | 0.6995 | 4.806 | 57.24 |
| 17 | 0.6945 | 8.646 | 0.2878 | 5.085 | 56.55 |
| 18 | 0.6849 | 8.928 | 0.1563 | 11.54 | 173.0 |
| 19 | 0.6914 | 10.66 | 0.1839 | 5.179 | 57.89 |
| 20 | 0.6954 | 10.4 | 0.4307 | 5.082 | 55.54 |
| 21 | 0.666 | 10.0 | 0.1 | 5.187 | 56.56 |
| 22 | 0.6803 | 6.808 | 0.3443 | 20.48 | 165.5 |
| 23 | 0.6867 | 8.836 | 0.8449 | 11.28 | 173.8 |
| 24 | 0.6947 | 11.46 | 0.4133 | 4.83 | 57.97 |
| 25 | 0.6946 | 13.18 | 0.247 | 2.346 | 48.64 |
| 26 | 0.6862 | 8.622 | 0.8044 | 5.59 | 57.08 |
| 27 | 0.6979 | 13.99 | 0.5065 | 11.18 | 84.77 |
| 28 | 0.6969 | 14.31 | 0.4357 | 11.01 | 83.97 |
| 29 | 0.7009 | 14.94 | 0.33 | 16.23 | 98.76 |
| 30 | 0.6964 | 14.95 | 0.4894 | 11.7 | 83.64 |
{‘target’: 0.7009402931111463, ‘params’: {‘max_depth’: 14.942382842424944, ‘max_features’: 0.33000163779169145, ‘min_samples_split’: 16.22846313016438, ‘n_estimators’: 98.76105059640975}}
放图片还是更清楚一点。
迭代过程:
最优结果:
从图中我们可以看到,贝叶斯优化一直在迭代搜索最优结果,在先验信息的基础上搜寻更优的结果。
调完参后的最优值,我们搜到是:
0.7009402931111463
相比默认有了0.18左右的提高。
把该组参数代入到原先的回归模型中,
n_estimators=99, max_features=0.33, max_depth=15, min_samples_split=16
运行的结果为:
测试集分数
0.6987540622657751
同样比默认参数结果更好。
总结:
贝叶斯调参相比于网格搜索更加方便快捷,逐渐成为程序员调参的第一选择。这只是最基本的调参,想要更好的结果则根据实验数据,调整超参数的取值范围和贝叶斯的迭代次数。如果结果还是不够理想可以调试不同的先验函数和采集函数,要根据具体的数据而定。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。