贝叶斯优化包的基础介绍

以下为该学习地址的学习笔记

学习地址:Basic tour of the Bayesian Optimization package — Bayesian Optimization documentation

贝叶斯优化简介

贝叶斯优化是一种基于贝叶斯推断和高斯过程的全局优化方法,它试图在尽可能少的迭代次数内找到一个未知函数的最大值。这种技术特别适合用于高成本函数的优化,以及需要在探索(exploration)和利用(exploitation)之间找到平衡的情况。

贝叶斯优化的基本原理

  1. 后验分布构建:贝叶斯优化通过构建一个描述你要优化的函数的后验分布(通常是高斯过程)来工作。随着观察数据的增加,后验分布会不断改进,算法会逐渐确定参数空间中的哪些区域值得探索,哪些不值得探索。

  2. 探索与利用的平衡:在每一步迭代中,算法都会根据已知样本(先前探索过的点)拟合一个高斯过程。然后,后验分布结合探索策略(如UCB(上置信界)或EI(期望改进))来确定下一个应该探索的点。

优化过程

贝叶斯优化的过程旨在最小化找到接近最优参数组合所需的步骤数。为此,这种方法使用了一个代理优化问题(寻找采集函数的最大值),虽然这仍然是一个困难的问题,但计算成本较低,并且可以使用常见的工具。因此,贝叶斯优化特别适用于采样目标函数非常昂贵的情况。

关键概念

  1. 高斯过程:一种用于构建后验分布的非参数贝叶斯模型,它通过已知样本来推断未知函数的分布。
  2. 采集函数:一种策略函数,用于在每次迭代中决定下一个采样点。常见的采集函数包括上置信界(UCB)和期望改进(EI)。
  3. 探索(Exploration)与利用(Exploitation):探索是指寻找参数空间中未知或不确定的区域,而利用是指在已知的高潜力区域进行优化。贝叶斯优化通过平衡这两者来提高优化效率。

应用场景

贝叶斯优化适用于以下情况:

  • 目标函数的计算代价高昂,例如机器学习模型的超参数调优。
  • 需要在尽量少的迭代中找到接近最优的参数组合。
  • 需要在探索新的参数区域和利用已有信息之间找到平衡。

通过贝叶斯优化,可以在高成本的函数优化问题中高效地找到最优解,减少不必要的计算开销。详细的讨论和更多的理论基础可以参考相关文献和资料。

1. 确定要优化的函数

这是一个函数优化软件包,因此最重要的第一要素当然是要优化的函数。

免责声明:我们很清楚下面函数的输出如何取决于其参数。显然,这只是一个示例,你不应该指望在实际场景中知道这一点。不过,你应该清楚,你并不需要知道。要使用这个软件包(更广泛地说,要使用这种技术),你所需要的只是一个接收已知参数集并输出实数的函数 f。

贝叶斯优化的核心是对函数进行优化。首先,需要定义一个目标函数(即需要优化的函数)。


def black_box_function(x, y):"""定义一个我们希望优化的未知内部函数。这里仅作为示例,在实际场景中,你不应该知道该函数的具体内部实现。只需要知道这个函数接受一组参数并输出一个实数即可。"""return -x ** 2 - (y - 1) ** 2 + 1

此函数返回一个值,该值基于输入参数 x和 y 计算得到。优化的目标是找到使得该函数值最大的参数组合。

2. 开始贝叶斯优化

我们需要实例化一个 BayesianOptimization 对象,指定要优化的函数 f 及其参数和对应的边界 pbounds。贝叶斯优化是一种约束优化技术,因此必须指定每个参数的最小和最大值。

from bayes_opt import BayesianOptimization# 参数空间的有界区域
pbounds = {'x': (2, 4), 'y': (-3, 3)}  # 指定参数 x 和 y 的边界optimizer = BayesianOptimization(f=black_box_function,  # 需要优化的函数pbounds=pbounds,       # 参数边界verbose=2,             # verbose=1 时仅在观察到最大值时打印,verbose=0 时不打印random_state=1,        # 随机种子,保证结果可重复
)

BayesianOptimization 对象可以直接使用,无需进行大量调优。主要需要关注的方法是 maximize,它用于执行贝叶斯优化过程。

maximize 方法接受多个参数,最重要的有:

  • n_iter:执行贝叶斯优化的步数,步数越多,找到好最大值的可能性越大。
  • init_points:执行随机探索的步数,随机探索有助于多样化探索空间。

optimizer.maximize(init_points=2,  # 初始随机探索步数n_iter=3,       # 贝叶斯优化步数
)

执行后,会显示每次迭代的参数组合及其对应的目标值(即函数值)。

markdown复制代码
|   iter    |  target   |     x     |     y     |
-------------------------------------------------
| 1         | -7.135    | 2.834     | 1.322     |
| 2         | -7.78     | 2.0       | -1.186    |
| 3         | -7.11     | 2.218     | -0.7867   |
| 4         | -12.4     | 3.66      | 0.9608    |
| 5         | -6.999    | 2.23      | -0.7392   |
=================================================

最佳参数组合及其对应的目标值可以通过 optimizer.max 属性访问。


print(optimizer.max)
# 输出最优参数及其对应的目标值
# {'target': -6.999472814518675, 'params': {'x': 2.2303920156083024, 'y': -0.7392021938893159}}

所有被探索的参数及其目标值可以通过 optimizer.res 属性访问。


for i, res in enumerate(optimizer.res):print("Iteration {}: \\n\\t{}".format(i, res))
# 逐次打印每次迭代的参数及目标值
# Iteration 0:
#         {'target': -7.135455292718879, 'params': {'x': 2.8340440094051482, 'y': 1.3219469606529488}}
# Iteration 1:
#         {'target': -7.779531005607566, 'params': {'x': 2.0002287496346898, 'y': -1.1860045642089614}}
# Iteration 2:
#         {'target': -7.109925819441113, 'params': {'x': 2.2175526295255183, 'y': -0.7867249801593896}}
# Iteration 3:
#         {'target': -12.397162416009818, 'params': {'x': 3.660003815774634, 'y': 0.9608275029525108}}
# Iteration 4:
#         {'target': -6.999472814518675, 'params': {'x': 2.2303920156083024, 'y': -0.7392021938893159}}

2.1 修改参数边界

在优化过程中,可能会发现某些参数的边界不合适。此时,可以调用 set_bounds 方法来修改它们。你可以传递任何现有参数及其新的边界组合。

示例代码

optimizer.set_bounds(new_bounds={"x": (-2, 3)})  # 修改参数 x 的边界为 [-2, 3]optimizer.maximize(    # 开始优化过程init_points=0,     # 初始随机探索步数设置为 0n_iter=5,          # 进行 5 次贝叶斯优化迭代
)

执行结果会显示每次迭代的参数组合及其对应的目标值(即函数值)。

  • iter: 迭代次数,即当前是第几次迭代。
  • target: 目标值,即目标函数在该次迭代的参数组合下计算得到的值。
  • x: 参数 x 的值。
  • y: 参数 y 的值。

|   iter    |  target   |     x     |     y     |
-------------------------------------------------
| 6         | -2.942    | 1.98      | 0.8567    |
| 7         | -0.4597   | 1.096     | 1.508     |
| 8         | 0.5304    | -0.6807   | 1.079     |
| 9         | -5.33     | -1.526    | 3.0       |
| 10        | -5.419    | -2.0      | -0.5552   |
=================================================

3. 指导优化过程

在优化过程中,我们通常对参数空间的某些区域有一定的了解,认为这些区域可能包含函数的最大值。对于这种情况,BayesianOptimization 对象允许用户指定特定的点进行探测。默认情况下,这些点会被懒惰地(lazy=True)探索,即这些点将在下次调用 maximize 时才会被评估。这个探测过程发生在高斯过程接管之前。

示例代码

可以将参数以字典形式传递,如下所示:


optimizer.probe(  # 使用 probe 方法指定要探测的点params={"x": 0.5, "y": 0.7},  # 指定 x 和 y 的值lazy=True,  # 懒惰探索,等到下次调用 maximize 时才评估这些点
)

也可以将参数作为可迭代对象传递。注意顺序必须是按字母顺序排列的。你可以使用 optimizer.space.keys 来查看顺序。


print(optimizer.space.keys)  # 打印参数的键,以确认顺序
# 输出: ['x', 'y']optimizer.probe(  # 使用 probe 方法指定要探测的点params=[-0.3, 0.1],  # 参数按字母顺序排列,即 x=-0.3, y=0.1lazy=True,  # 懒惰探索,等到下次调用 maximize 时才评估这些点
)

接下来调用 maximize 方法执行优化:


optimizer.maximize(init_points=0, n_iter=0)  # 进行优化,此处 init_points 和 n_iter 均为 0 表示只评估探测点
  • init_points
    • 表示在正式开始贝叶斯优化之前,进行随机探索的步数。
    • 随机探索可以帮助多样化探索空间,但并不利用贝叶斯优化的优点。
  • n_iter
    • 表示实际进行贝叶斯优化的步数。
    • 贝叶斯优化利用已有数据和高斯过程模型来选择下一个探索点,以最大化目标函数。
  • lazy=True
    • 表示指定的探测点将在下次调用 maximize 时被评估。
    • 如果 lazy=False,探测点会立即被评估。

执行结果会显示每次迭代的参数组合及其对应的目标值(即函数值)。


|   iter    |  target   |     x     |     y     |
-------------------------------------------------
| 11        | 0.66      | 0.5       | 0.7       |
| 12        | 0.1       | -0.3      | 0.1       |
=================================================
  • 指定探测点
    • 通过 optimizer.probe 方法指定一些参数组合(探测点)用于评估。
    • 设置 lazy=True 表示这些探测点不会立即被评估,而是在下次调用 maximize 时才会被评估。
  • 调用 maximize 方法
    • 通过 optimizer.maximize(init_points=0, n_iter=0),告诉优化器这次优化不进行任何额外的随机探索(init_points=0)和贝叶斯优化步骤(n_iter=0)。
    • 由于设置了 lazy=True,因此这些探测点在这次 maximize 调用时被评估。

这样做的意义在于,你可以提前指定一些感兴趣的点,让优化器在正式开始贝叶斯优化之前先评估这些点。这对于你有某些先验知识或猜测可能有用的参数区域时非常有效。

3.1 补充

1. 探测点(Probing Points)

探测点是你认为可能重要或有趣的参数组合,提前指定这些点用于目标函数的计算。你可以使用 optimizer.probe 方法来指定这些点。

python复制代码
optimizer.probe(params={"x": 0.5, "y": 0.7},lazy=True,  # 表示这些探测点在下次调用 maximize 时才会被评估
)

2. 评估(Evaluation)

评估是指对指定的探测点进行目标函数的计算。也就是说,把这些探测点作为参数代入目标函数,计算得到对应的目标值。

3. maximize 方法的调用

optimizer.maximize(init_points=0, n_iter=0) 表示这次优化过程中不进行任何额外的随机探索(init_points=0)和贝叶斯优化步骤(n_iter=0),只对之前通过 optimizer.probe 指定的探测点进行评估。

如下这个代码示例,执行这段代码时,maximize 方法会评估之前指定的探测点 (0.5, 0.7) 和 (-0.3, 0.1),并将评估结果记录下来。这些结果将用于更新贝叶斯优化模型,从而帮助优化算法更好地寻找目标函数的最大值。

#示例
from bayes_opt import BayesianOptimization# 目标函数
def black_box_function(x, y):return -x ** 2 - (y - 1) ** 2 + 1# 定义参数空间的边界
pbounds = {'x': (2, 4), 'y': (-3, 3)}# 创建贝叶斯优化对象
optimizer = BayesianOptimization(f=black_box_function,pbounds=pbounds,verbose=2,  # 设置输出级别random_state=1,
)# 指定探测点
optimizer.probe(params={"x": 0.5, "y": 0.7},  # 参数 x=0.5, y=0.7lazy=True,  # 懒惰评估,这些点会在下次调用 maximize 时进行评估
)# 指定另一个探测点
optimizer.probe(params=[-0.3, 0.1],  # 参数按字母顺序排列,即 x=-0.3, y=0.1lazy=True,  # 懒惰评估,这些点会在下次调用 maximize 时进行评估
)# 进行优化,此次 maximize 调用只评估指定的探测点
optimizer.maximize(init_points=0, n_iter=0)

4. 保存、加载和重启

默认情况下,通过设置 verbose > 0 可以跟踪优化的进度。如果需要更高级的日志记录或警报控制,可以使用观察者模式。这里我们将看到如何使用内置的 JSONLogger 对象来保存和加载进度。

4.1 保存进度

首先,导入所需的库:


from bayes_opt.logger import JSONLogger  # 导入 JSONLogger 用于记录日志
from bayes_opt.event import Events  # 导入 Events 用于触发事件

观察者模式的工作原理如下:

  1. 实例化观察者对象。
  2. 将观察者对象与优化器触发的特定事件绑定。

贝叶斯优化对象在优化过程中会触发多个内部事件,特别是每次探测函数并获得新的参数-目标组合时,会触发 Events.OPTIMIZATION_STEP 事件,日志记录器将监听该事件。


logger = JSONLogger(path="./logs.log")  # 创建 JSONLogger 对象,指定日志文件路径
optimizer.subscribe(Events.OPTIMIZATION_STEP, logger)  # 订阅优化步骤事件,将其与日志记录器绑定optimizer.maximize(  # 开始优化init_points=2,  # 初始随机探测点数量n_iter=3,  # 贝叶斯优化的迭代次数
)
itertargetxy
13-12.48-1.266-2.446
14-3.854-1.069-0.9266
15-3.5940.77093.0
160.82380.034341.418
170.9721-0.10510.87

4.2 加载进度

如果保存了进度,可以将其加载到一个新的贝叶斯优化实例中。最简单的方法是调用 load_logs 函数。

  • 创建一个新的贝叶斯优化实例:用于优化一个目标函数 black_box_function
  • 加载先前保存的优化进度:从日志文件 logs.log 中恢复已经探测过的点。
  • 继续优化过程:在加载了之前的进度后,进行更多的贝叶斯优化迭代。
  • 通过这段代码,你可以在不同的会话或运行中保存和加载贝叶斯优化的进度。这对于长时间运行的优化任务特别有用,因为你可以中途暂停,然后在加载进度后继续优化。这段代码展示了如何使用贝叶斯优化包的日志功能来保存和加载优化进度,并在新的优化器实例中继续优化过程。

from bayes_opt.util import load_logs  # 导入 load_logs 函数new_optimizer = BayesianOptimization(  # 创建新的贝叶斯优化对象f=black_box_function,  # 目标函数pbounds={"x": (-2, 2), "y": (-2, 2)},  # 参数空间的边界verbose=2,  # 输出级别random_state=7,  # 随机种子
)
#这一步创建了一个新的 BayesianOptimization 对象,并指定了要优化的函数、参数边界、输出级别和随机种子。print(len(new_optimizer.space))  # 输出当前优化器空间中的点数
# 输出: 0  # 初始时点数为0
# 在没有加载日志之前,优化器空间中的点数为0。load_logs(new_optimizer, logs=["./logs.log"])  # 加载之前保存的日志文件
# 这一步从指定的日志文件 logs.log 中加载先前的优化进度,包括已经探测过的参数点和对应的目标值。print("New optimizer is now aware of {} points.".format(len(new_optimizer.space)))  # 输出当前优化器空间中的点数
# 输出: New optimizer is now aware of 5 points.
# 加载日志后,优化器现在知道5个点(假设日志中保存了5个探测点)。new_optimizer.maximize(  # 继续优化init_points=0,  # 不进行初始随机探测n_iter=10,  # 贝叶斯优化的迭代次数
)
# 这一步在加载了之前的进度后,进行10次贝叶斯优化迭代,以进一步探索和优化目标函数。
itertargetxy
1-3.548-2.01.74
2-3.0411.9140.3844
3-12.02.0-2.0
4-3.9692.01.984
5-0.7794-1.2380.5022
60.5290.6850.9576
70.29870.12420.1718
80.95440.21230.9766
90.7157-0.4371.305
100.983-0.067851.111

下一步

这部分内容应该足以覆盖此包的大多数使用场景。如果需要了解更多,请查阅高级教程笔记本。在那里,你可以找到此包的其他高级功能,这些功能可能正是你所寻找的。此外,还可以浏览示例文件夹,获取实现技巧和灵感。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/42760.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Dison夏令营 Day 12】如何用 Python 构建数独游戏

通过本综合教程,学习如何使用 Pygame 在 Python 中创建自己的数独游戏。本指南涵盖安装、游戏逻辑、用户界面和计时器功能,是希望创建功能性和可扩展性数独益智游戏的爱好者的理想之选。 数独是一种经典的数字谜题,多年来一直吸引着谜题爱好…

实例方法与静态方法的区别与使用场景

实例方法与静态方法的区别与使用场景 大家好,我是免费搭建查券返利机器人省钱赚佣金就用微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! 实例方法与静态方法的区别 在面向对象编程中,方法可以分为实…

昇思MindSpore25天学习Day19:CycleGAN图像风格迁移互换

(TOC)[CycleGAN图像风格迁移呼唤] 模型介绍 模型简介 CycleGAN(Cycle Generative Adversaial Network)即循环对抗生成网络,来自论文Link:Unpaired lmage-to-mage Translation using Cycle-Consistent AdvesairalNetworks该模型实现了—种在没有配对示例的情况下学…

从nginx返回404来看http1.0和http1.1的区别

序言 什么样的人可以称之为有智慧的人呢?如果下一个定义,你会如何来定义? 所谓智慧,就是能区分自己能改变的部分,自己无法改变的部分,努力去做自己能改变的,而不要天天想着那些无法改变的东西&a…

解析Java中的反射机制及其应用场景

解析Java中的反射机制及其应用场景 大家好,我是微赚淘客系统3.0的小编,也是冬天不穿秋裤,天冷也要风度的程序猿! Java的反射机制是指在运行时可以动态地获取类的信息(如类名、方法、字段等),并…

麒麟桌面操作系统上网络设置界面消失的解决方法

原文链接:麒麟桌面操作系统上网络设置界面消失的解决方法 Hello,大家好啊!今天给大家带来一篇关于麒麟桌面操作系统上网络设置界面消失解决方法的文章。在使用麒麟桌面操作系统时,可能会遇到网络设置界面突然消失的情况&#xff…

斯坦福CS224n深度学习培训营课程

自然语言处理领域的经典课程涵盖了从基础知识到最新研究的全面内容。本培训营将精选课程内容,结合实际案例和项目实践,带领学员深入探索自然语言处理的前沿,学习最先进的深度学习技术。 课程大小:2.6G 课程下载:http…

Softmax函数的意义

来自GPT,后期会再整理。。。 Softmax函数在深度学习中,特别是在多分类任务中,被广泛用作输出层的激活函数。它将模型的原始输出(logits)转化为概率分布,使得每个类别的概率总和为1。相比于简单地使用“单个…

四自由度SCARA机器人的运动学和动力学matlab建模与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 针对SCARA 机器人系统进行了深入研究与探讨,提出SCARA机器人的动力学模型和运动学模型,并以MATLAB软件为仿真平台,通过MATLAB Robotics Too…

java核心-泛型

目录 概述什么是泛型分类泛型类泛型接口泛型方法 泛型通配符分类 泛型类型擦除分类无限制类型擦除有限制类型擦除 问题需求第一种第二种 概述 了解泛型有利于学习 jdk 、中间件的源码,提升代码抽象能力,封装通用性更强的组件。 什么是泛型 在定义类、接…

二手闲置平台小程序的设计

管理员账户功能包括:系统首页,个人中心,用户管理,卖家管理,商品分类管理,商品信息管理,商品购买管理,商品配送管理 微信端账号功能包括:系统首页,商品信息&a…

qt中connect函数的使用方法

bool QObject::connect(const QObject *sender, const char *signal,const QObject *receiver, const char *method,Qt::ConnectionType type Qt::AutoConnection);1.sender: 一个指向信号发送者的QObject指针。这是发出信号的对象,可以是任何继承自QObject的类的实…

【linux服务器】大语言模型实战教程:LLMS大模型部署到个人服务器或嵌入式开发板(保姆级教学)

🎬 鸽芷咕:个人主页 🔥 个人专栏: 《C干货基地》《粉丝福利》 ⛺️生活的理想,就是为了理想的生活! 引言 说到大语言模型相信大家都不会陌生,大型语言模型(LLMs)是人工智能文本处理的主要类型,也现在最流行的人工智能…

基于Java+SpringMvc+Vue技术智慧校园系统设计与实现--60页及以上论文参考

博主介绍:硕士研究生,专注于信息化技术领域开发与管理,会使用java、标准c/c等开发语言,以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架…

网络基础:园区网络架构

园区网络 园区网络(Campus Network)是指在一个相对较大的区域内,如大学校园、企业园区或政府机关等,建立的计算机网络系统。园区网络根据规模的不同,可以分为以下几种类型: ①小型园区网络:通常…

WebKit中Websockets的全面支持:实现高效实时通信

WebKit中Websockets的全面支持:实现高效实时通信 Websockets是一种网络通信协议,它允许在单个TCP连接上进行全双工通信,从而实现服务器与客户端之间的实时数据交换。WebKit作为许多流行浏览器的底层引擎,对Websockets提供了全面的…

Java 多线程工具类 Semaphore

引言 在多线程编程中,控制对共享资源的访问是一个关键问题。Java 提供了多种同步机制来解决这个问题,其中 Semaphore 是一种常用的工具类,用于限制可以同时访问某个资源的线程数。本文将详细介绍 Semaphore 的概念、使用方法和实际应用场景。…

ARM GEC6818 LCD绘图 实心圆 三角形 五角星 任意区域矩形以及旗帜

要在ARM上实现LCD绘图,可以按照以下步骤进行: 硬件初始化:初始化LCD控制器和相关引脚,配置时钟、分辨率和颜色深度等。 内存映射:将LCD显示区域映射到ARM的内存地址空间中,可以通过ARM的内存映射机制来实现。 绘图函数:实现绘制基本图形的函数,如点、线、矩形、圆等。可…

【系统架构设计师】八、系统工程基础知识(系统工程|系统性能)

目录 一、系统工程 1.1 系统工程的方法 1.1.1 霍尔的三维结构 1.1.2 切克兰德方法 1.1.3 并行工程方法 1.1.4 综合集成法 1.1.5.WSR 系统方法。 二、系统工程生命周期 2.1 系统工程生命周期7阶段 2.2 生命周期方法 三、基于模型的系统工程(MBSE) 四、系统性能 4.1…

vb.netcad二开自学笔记6:第一个绘制线段命令

.net编写绘制直线已完全不同于ActiveX的(VBA)的方式,过程更类似于arx程序,需要通过操作AutoCAD 数据库添加对象!下面的代码是在以前代码基础上添加了一个新myline命令。 AutoCAD 数据库结构 myline命令代码 Imports A…