贝叶斯优化器

基于github上的一个贝叶斯优化开源项目,其用法在项目的说明中有详细英文记录,这里主要是整理简化,并参考了其他文献来记录一下项目中用的数学函数以及论文中一些单词的说明。

原理

这篇文章(参考一)从详细说明了该项目的核心思想和过程,包括该过程用到的先验函数和采集函数的介绍。博客和github项目里面都提到了exploration与exploitation这两个单词。可以解释为不确定策略的探索(Exploration)和当前策略的开采(Exploitation)之间进行权衡,也可以理解为explore是在未知领域进行探索,exploit是在已有范围进行开发利用;Exploration 是要在全局范围内搜索,避免陷入局部最优,Exploitation 是要在当前最优的附近搜索,找到更好的解。即:

探索(exploration):简单来说就是尽量选择远离已知点的点为下一次用于迭代的参考点,即尽量探索未知的区域,点的分布会尽可能的平均。
利用(exploitation):简单来说就是尽量选择靠近已知点的点为下一次用于迭代的参考点,即尽量挖掘已知点周围的点,点的分布会出现一个密集区域,容易进入局部最大

def BayesianOptimization(target,x,Y):
    IF 初始化?
        Yes: 
            xold为已知的所有点中目标函数取得最大值的自变量值
            IF target(xold)>Y?     
                Yes:   return xold,target(xold)    #撞了大运,还没开始迭代就结束了
                No:    Pass
        No:  随机初始化
    While    target(xnew)<Y:
        利用PF(高斯过程回归)求解未知点(在事先定义的自变量范围内,有成千上万个未知点)的均值与方差
        利用AC(EI或PI或UCB)找到贝叶斯优化器猜测的最大值的点xnew,一般是AC函数最大点
    return   xnew,target(new)

x:自变量取值范围,Y:可以接受的黑箱函数因变量取值。这其中的两个核心过程为先验函数(Prior Function,PF)与采集函数(Acquisition Function,AC),采集函数也可以叫效能函数(Utility Funtcion)。先验函数(高斯过程回归)是计算每一点处函数值的均值和方差,根据均值和方差来构造采集函数,用以决定你个本次迭代时在哪个点处进行采样。

其具体的高斯过程回归方程和采集函数可以参考二这里

引用上面提到的文章来概括其主要过程,方程的数学过程细节还是直接参考原作者吧。

算法的思路是首先生成一个初始候选解集合,然后根据这些点寻找下一个有可能是极值的点,将该点加入集合中,重复这一步骤,直至迭代终止。最后从这些点中找出极值点作为问题的解。

这里的关键问题是如何根据已经搜索的点确定下一个搜索点。贝叶斯优化根据已经搜索的点的函数值估计真实目标函数值的均值和方差(即波动范围),如图所示。上图中红色的曲线为估计出的目标函数值即在每一点出处的目标函数值的均值。现在有3个已经搜索的点,用黑色实心点表示。两条虚线所夹区域为在每一点处函数值的变动范围,在以均值即红色曲线为中心,与标准差成正比的区间内波动。在搜索点处,红色曲线经过搜索点,且方差最小,在远离搜索点处方差更大,这也符合我们的直观认识,远离采样点处的函数值估计的更不可靠。

根据均值和方差可以构造出采集函数(acquisition function),即对每一点是函数极值点的可能性的估计,反映了每一个点值得搜索的程度,该函数的极值点是下一个搜索点,如下图所示。下图中的矩形框所表示的点是采集函数的极大值点,也是下一个搜索点

算法的核心由两部分构成:对目标函数进行建模即计算每一点处的函数值的均值和方差,通常用高斯过程回归实现;构造采集函数,用于决定本次迭代时在哪个点处进行采样。

 

 理解到这里的概括后,再次看参考一文章里的step1-9的图片就比较好理解了。

使用方式

初级入门

接下来就是照搬github上的教程了。

想要使用贝叶斯优化只需要三个部分,优化参数,目标方程,优化器

目标方程:例子给的是一个两元函数,这里也可以是机器学习训练的一个项目。

from bayes_opt import BayesianOptimization

def black_box_function(x, y):

    return -x ** 2 - (y - 1) ** 2 + 1

优化参数:机器学习的话,一般指的是超参数。这里是X,Y。并设定好参数的区间。

优化器的设置,直接使用BayesianOptimization进行初始化

pbounds = {'x': (2, 4), 'y': (-3, 3)}
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,
)

f=black_box_function 这里比较简单指的就是一个函数。如果是机器学习,这里定义的函数可以是完整的一个项目,调用这个函数来进行项目的启动,最后返回相应的结果就可以。

接下来就可以进行迭代寻优了

optimizer.maximize(
    init_points=2,
    n_iter=3,
)

这里面涉及到两个参数,init_point和n_iter

n_iter: 总共迭代的次数。

init_point:这个是随机点执行的次数。上面的基础理论部分提到,贝叶斯优化是建立在上一次优化的基础上进行优化。这是exploitation部分。但是想要exploration,扩大全局最优的可能,使用init_point来控制,直接使用随机点而不依赖上次计算的结果。

最终打印出整个迭代后的最优结果(最后的几次不一定是最优解)

print(optimizer.max)

想要打印出每次迭代的结果

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

可以通过一下命令重新设置参数的边界

optimizer.set_bounds(new_bounds={"x": (-2, 3)})
optimizer.maximize(
    init_points=0,
    n_iter=5,
)

还有一种情况就是引导优化,我们觉得参数的某个值的范围内可能存在最大值,可以使用这个命令设置:

optimizer.probe(
    params={"x": 0.5, "y": 0.7},
    lazy=True,
)

lazy表示这延迟写入该值。这个时候在下次调用max函数的时候将设置的参数值写入到优化器,并计算。

可以连续写入:

optimizer.probe(
    params=[-0.3, 0.1],
    lazy=True,
)

调用maximize

optimizer.maximize(init_points=0, n_iter=0)

结果:

|   iter    |  target   |     x     |     y     |
-------------------------------------------------
|  11       |  0.66     |  0.5      |  0.7      |
|  12       |  0.1      | -0.3      |  0.1      |
=================================================

运行过程数据的保存与恢复

保存:之前就之使用了个优化器类,通过设置该类的初始化参数verbose也可以看到运行中的状态。如果想要保存到本地文件内,可以使用如下流程:

from bayes_opt.logger import JSONLogger
from bayes_opt.event import Events

logger = JSONLogger(path="./logs.json")
optimizer.subscribe(Events.OPTIMIZATION_STEP, logger)
optimizer.maximize(
    init_points=2,
    n_iter=3,
)

应当注意的是,只会记录当前以及以后的数据。

加载:一方面可以加载已经优化的过程数据,另一方面可以直接作用在另外一个新的优化器上。

from bayes_opt.util import load_logs
new_optimizer = BayesianOptimization(
    f=black_box_function,
    pbounds={"x": (-2, 2), "y": (-2, 2)},
    verbose=2,
    random_state=7,
)
print(len(new_optimizer.space))

load_logs(new_optimizer, logs=["./logs.json"]);
new_optimizer.maximize(
    init_points=0,
    n_iter=10,
)

高级进阶

其实通过上面初级入门的教程已经适用绝大部分的场景。高级进阶的部分主要是细化优化器执行的每一步的具体过程。比如说optimizer.maximize其实是执行了suggest,  probe以及 register方法。

通过前面文献一和文献二的理论基础我们知道优化器的一次迭代大概经历如下:定义目标,初始化变量(更新后变量值),采集函数确定变量更新位置,计算目标值。在初级入门教程中直接使用maximize一个方法将这些全部包括。其实可以拆分为如下步骤:

from bayes_opt import UtilityFunction
# 定义目标函数
def black_box_function(x, y):
    return -x ** 2 - (y - 1) ** 2 + 1

optimizer = BayesianOptimization(
    f=None,  # 先定义为空
    pbounds={'x': (-2, 2), 'y': (-3, 3)},#自定义变量范围
    verbose=2,
    random_state=1,
)
#采集函数的选取以及提到的探索exploration和利用exploitation的平衡参数的确定
utility = UtilityFunction(kind="ucb", kappa=2.5, xi=0.0)
# 确定变量的下个位置
next_point_to_probe = optimizer.suggest(utility)
print("Next point to probe is:", next_point_to_probe)
# 计算目标函数值
target = black_box_function(**next_point_to_probe)
print("Found the target value to be:", target)
# 写入优化器
optimizer.register(
    params=next_point_to_probe,
    target=target,
)

以上程序写好后,只会执行一次。循环执行的方式为:

for _ in range(5):
    next_point = optimizer.suggest(utility)
    target = black_box_function(**next_point)
    optimizer.register(params=next_point, target=target)
    print(target, next_point)
print(optimizer.max)

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
作为一名AI语言模型,我无法直接优化代码,但是我可以给您提供一些关于使用贝叶斯优化优化卷积神经网络的建议。贝叶斯优化是一种优化算法,它可以在较少的尝试次数内找到最优解。在卷积神经网络中,我们可以使用贝叶斯优化来调整超参数,例如学习率、批量大小、卷积核大小等。 以下是一些使用贝叶斯优化优化卷积神经网络的步骤: 1. 定义目标函数:在这个步骤中,我们需要定义一个目标函数来衡量模型的性能。通常情况下,我们会使用交叉熵损失函数或均方误差函数来衡量模型的性能。 2. 定义超参数空间:在这个步骤中,我们需要定义一个超参数空间,包含我们希望调整的超参数。例如,我们可以定义一个学习率范围为0.001到0.1,批量大小范围为32到128,卷积核大小范围为3x3到5x5。 3. 初始化贝叶斯优化:在这个步骤中,我们需要初始化贝叶斯优化,并将目标函数和超参数空间作为参数传递给它。 4. 迭代优化:在这个步骤中,我们需要迭代地使用贝叶斯优化来寻找最优超参数。在每次迭代中,贝叶斯优化会根据当前的超参数空间中的已知点和目标函数的输出来选择下一个点进行评估。然后,我们使用选择的超参数来训练模型,并计算其在验证集上的性能。最后,我们将性能作为目标函数的输出,传递给贝叶斯优化,以便它可以选择下一个点进行评估。 5. 评估最优超参数:在迭代完成后,我们可以从贝叶斯优化中获取最优超参数,并将其用于训练最终的模型。 需要注意的是,贝叶斯优化是一种黑盒优化算法,它并不知道我们的模型的内部结构。因此,在使用贝叶斯优化优化卷积神经网络时,我们需要将不同的超参数组合作为模型的输入,并在目标函数中评估其性能。同时,我们还需要选择合适的目标函数和超参数空间,以提高贝叶斯优化的效率和准确性。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值