bayes调参

转自:http://www.javashuo.com/article/p-avbjwgvm-gm.html

1、简介

贝叶斯优化用于机器学习调参由J. Snoek(2012)提出,主要思想是,给定优化的目标函数(广义的函数,只需指定输入和输出便可,无需知道内部结构以及数学性质),经过不断地添加样本点来更新目标函数的后验分布(高斯过程,直到后验分布基本贴合于真实分布。简单的说,就是考虑了上一次参数的信息**,从而更好的调整当前的参数。html

他与常规的网格搜索或者随机搜索的区别是:python

  • 贝叶斯调参采用高斯过程,考虑以前的参数信息,不断地更新先验;网格搜索未考虑以前的参数信息
  • 贝叶斯调参迭代次数少,速度快;网格搜索速度慢,参数多时易致使维度爆炸
  • 贝叶斯调参针对非凸问题依然稳健;网格搜索针对非凸问题易获得局部优最

2、理论

介绍贝叶斯优化调参,必需要从两个部分讲起:git

  • 高斯过程,用以拟合优化目标函数
  • 贝叶斯优化,包括了“开采”和“勘探”,用以花最少的代价找到最优值

2.1 高斯过程

高斯过程能够用于非线性回归、非线性分类、参数寻优等等。以往的建模须要对 p(y|X)github

建模,当用于预测时,则是算法

 

p(yN+1|XN+1)

 

而高斯过程则, 还考虑了 yN数组

yN+1bash

之间的关系,即:app

 

p(yN+1|XN+1,yN)

 

高斯过程经过假设 Ydom

值服从联合正态分布,来考虑 yNyN+1机器学习

之间的关系,所以须要给定参数包括:均值向量和协方差矩阵,即:

 

y1y2...ynN(0,k(x1,x1),k(x1,x2),...,k(x1,xn)k(x2,x1),k(x2,x2),...,k(x2,xn)...k(xn,x1),k(xn,x2),...,k(xn,xn))

 

其中协方差矩阵又叫作 核矩阵, 记为 K

,仅和特征 x 有关,和 y

无关。

高斯过程的思想是: 假设 Y

服从高维正态分布(先验),而根据训练集能够获得最优的核矩阵 ,从而获得后验以估计测试集 Y

 

咱们有后验:

 

p(y|yN(KK1y, KKK1KT)

 

其中,K

为训练集的核向量,有以下关系:

 

[yy]N(0,[K,KTK,K])

 

能够发现,在后验公式中,只有均值和训练集 Y

有关,方差则仅仅和核矩阵,也就是训练集和测试集的 X 有关,与训练集 Y

无关

高斯过程的估计(训练)方法

假设使用平方指数核(Squared Exponential Kernel),那么有:

 

k(x1,x2)=σ2fexp((x1x2)22l2)

 

那么所须要的肯定的超参数 θ=[σ2f,l]

,因为 Y

服从多维正态分布,所以似然函数为:

 

L=logp(y|x,θ)=12log|K|12(yμ)TK1(yμ)nlog(2π)/2

 

因为 K

是由 θ 决定的,因此经过梯度降低便可求出超参数 θ

,而根据核矩阵的计算方式也能够进行预测。

上图是一张高斯分布拟合函数的示意图,能够看到,它只须要九个点,就能够大体拟合出整个函数形状(图片来自:https://github.com/fmfn/BayesianOptimization

2.2 贝叶斯优化理论

贝叶斯优化是一种逼近思想,当计算很是复杂、迭代次数较高时能起到很好的效果,多用于超参数肯定

基本思想

是基于数据使用贝叶斯定理估计目标函数的后验分布,而后再根据分布选择下一个采样的超参数组合。它充分利用了前一个采样点的信息,其优化的工做方式是经过对目标函数形状的学习,并找到使结果向全局最大提高的参数

高斯过程 用于在贝叶斯优化中对目标函数建模,获得其后验分布

经过高斯过程建模以后,咱们尝试抽样进行样本计算,而贝叶斯优化很容易在局部最优解上不断采样,这就涉及到了开发和探索之间的权衡。

  • 开发 (exploitation): 根据后验分布,在最可能出现全局最优解的区域进行采样, 开发高意味着均值高
  • 探索 (exploration): 在还未取样的区域获取采样点, 探索高意味着方差高

而如何高效的采样,即开发和探索,咱们须要用到 Acquisition Function, 它是用来寻找下一个 x 的函数。

Acquistion Function

通常形式的Acquisition Funtion是关于x的函数,映射到实数空间R,表示改点的目标函数值可以比当前最优值大多少的几率,目前主要有如下几种主流的Acquisition Function

POI(probability of improvement)

 

POI(X)=P(f(X)f(X+)+ξ)=Φ(μ(x)f(X+)ξσ(x))

 

其中, f(X)

为X的目标函数值, f(X+)到目前为止 最优的X的目标函数值, μ(x),σ(x) 分别是高斯过程所获得的目标函数的均值和方差,即 f(X) 的后验分布。 ξ 为trade-off系数,若是没有该系数,POI函数会倾向于取在 X+

周围的点,即倾向于exploit而不是explore,所以加入该项进行权衡。

而咱们要作的,就是尝试新的X,使得 POI(X)

最大,则采起该X (由于f(X)

的计算代价很是大),一般咱们使用 蒙特卡洛模拟 的方法进行。

详细状况见下图(图片来自 Ref[5])

Expected Improvement

POI是一个几率函数,所以只考虑了f(x) 比 f(x+)

大的几率,而EI则是一个指望函数,所以考虑了 f(x) 比 f(x+)

大多少。咱们经过下式获取x

 

x=argmaxx  E(max{0,ft+1(x)f(X+)}|Dt)

 

其中 Dt

为前t个样本,在正态分布的假定下,最终获得:

 

EI(x)={(μ(x)f(x+))Φ(Z)+σ(x)ϕ(Z),if σ(x)>00,if σ(x)=0

 

其中 Z=μ(x)f(x+)σ(x)

 

Confidence bound criteria

 

LCB(x)=μ(x)κσ(x)

 

 

UCB(x)=μ(x)+κσ(x)

 

2.3 缺点和不足

  • 高斯过程核矩阵很差选

3、例子

目前能够作贝叶斯优化的包很是多,光是python就有:

本文使用BayesianOptimization为例,利用sklearn的随机森林模型进行分类

安装

pip install bayesian-optimization

前期准备

from sklearn.datasets import make_classification from sklearn.ensemble import RandomForestClassifier from sklearn.cross_validation import cross_val_score from bayes_opt import BayesianOptimization # 产生随机分类数据集,10个特征, 2个类别 x, y = make_classification(n_samples=1000,n_features=10,n_classes=2)

咱们先看看不调参的结果:

rf = RandomForestClassifier()
print(np.mean(cross_val_score(rf, x, y, cv=20, scoring='roc_auc'))) >>> 0.965162

能够看到,不调参的话模型20此交叉验证AUC均值是0.965162,算是一个不错的模型,那么若是用bayes调参结果会怎么样呢

bayes调参初探

咱们先定义一个目标函数,里面放入咱们但愿优化的函数。好比此时,函数输入为随机森林的全部参数,输出为模型交叉验证5次的AUC均值,做为咱们的目标函数。由于bayes_opt库只支持最大值,因此最后的输出若是是越小越好,那么须要在前面加上负号,以转为最大值。因为bayes优化只能优化连续超参数,所以要加上int()转为离散超参数。

def rf_cv(n_estimators, min_samples_split, max_features, max_depth): val = cross_val_score( RandomForestClassifier(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 ), x, y, scoring='roc_auc', cv=5 ).mean() return val 

而后咱们就能够实例化一个bayes优化对象了:

rf_bo = BayesianOptimization(
        rf_cv,
        {'n_estimators': (10, 250), 'min_samples_split': (2, 25), 'max_features': (0.1, 0.999), 'max_depth': (5, 15)} )

里面的第一个参数是咱们的优化目标函数,第二个参数是咱们所须要输入的超参数名称,以及其范围。超参数名称必须和目标函数的输入名称一一对应。

完成上面两步以后,咱们就能够运行bayes优化了!

rf_bo.maximize()

完成的时候会不断地输出结果,以下图所示:

等到程序结束,咱们能够查看当前最优的参数和结果:

rf_bo.res['max'] >>> {'max_params': {'max_depth': 5.819908283575526, 'max_features': 0.4951745603509127, 'min_samples_split': 2.3110014720414958, 'n_estimators': 249.73529231990733}, 'max_val': 0.9774079407940794}

bayes调参进阶

上面bayes算法获得的参数并不必定最优,固然咱们会遇到一种状况,就是咱们已经知道有一组或是几组参数是很是好的了,咱们想知道其附近有没有更好的。这个操做至关于上文bayes优化中的Explore操做,而bayes_opt库给了咱们实现此方法的函数:

rf_bo.explore(
    {'n_estimators': [10, 100, 200], 'min_samples_split': [2, 10, 20], 'max_features': [0.1, 0.5, 0.9], 'max_depth': [5, 10, 15] } )

这里咱们添加了三组较优的超参数,让其在该参数基础上进行explore,可能会获得更好的结果。

同时,咱们还能够修改高斯过程的参数,高斯过程主要参数是核函数(kernel),还有其余参数能够参考sklearn.gaussianprocess

gp_param={'kernel':None} rf_bo.maximize(**gp_param)

最终咱们的到参数以下:

{'max_params': {'max_depth': 5.819908283575526, 'max_features': 0.4951745603509127, 'min_samples_split': 2.3110014720414958, 'n_estimators': 249.73529231990733}, 'max_val': 0.9774079407940794}

运行交叉验证测试一下:

rf = RandomForestClassifier(max_depth=6, max_features=0.39517, min_samples_split=2, n_estimators=250) np.mean(cross_val_score(rf, x, y, cv=20, scoring='roc_auc')) >>> 0.9754953

获得最终结果是0.9755,比以前的0.9652提升了约0.01,作过kaggle的朋友都懂,这在后期已是很是大的提升了!到后面想提升0.001都极其困难,所以bayes优化真的很是强大!

结束!

Reference

相关文章
相关标签/搜索