贝叶斯优化包的基础介绍

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

学习地址: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,     # 初始随机探索步数设置为 0
    n_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.1
    lazy=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.7
    lazy=True,  # 懒惰评估,这些点会在下次调用 maximize 时进行评估
)

# 指定另一个探测点
optimizer.probe(
    params=[-0.3, 0.1],  # 参数按字母顺序排列,即 x=-0.3, y=0.1
    lazy=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.mfbz.cn/a/782384.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

触发器编程-创建(CREATE TRIGGER)、删除(DROP TRIGGER)

一、定义 1、触发器(Trigger)是用户对某一表中的数据做插入、更新和删除操作时被处罚执行的一段程序,通常我们使用触发器来检查用户对表的操作是否合乎整个应用系统的需求,是否合乎商业规则以维持表内数据的完整性和正确性 2、一…

SPL-404:如何彻底改变Solana上的NFT与DeFi

在不断发展的数字资产领域中,非同质化Token(NFT)已成为一股革命性力量,彻底改变了我们对数字所有权的看法和互动方式。从艺术和收藏品到游戏和虚拟房地产,NFT吸引了创作者、投资者和爱好者的想象力。 本指南将带您进入…

力扣-双指针1

何为双指针 双指针指向同一数组,然后配合着进行搜索等活动。 滑动窗口的时候很好使用。 167.两数之和Ⅱ-输入有序数组 167. 两数之和 II - 输入有序数组 题目 给你一个下标从 1 开始的整数数组 numbers ,该数组已按 非递减顺序排列 ,请你从…

[Flink]三、Flink1.13

11. Table API 和 SQL 如图 11-1 所示,在 Flink 提供的多层级 API 中,核心是 DataStream API ,这是我们开发流 处理应用的基本途径;底层则是所谓的处理函数( process function ),可以访…

Android 简单快速实现 下弧形刻度尺(滑动事件)

效果图: 直接上代码: package com.my.view;import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Pai…

iptables实现端口转发ssh

iptables实现端口转发 实现使用防火墙9898端口访问内网front主机的22端口(ssh连接) 1. 防火墙配置(lb01) # 配置iptables # 这条命令的作用是将所有目的地为192.168.100.155且目标端口为19898的TCP数据包的目标IP地址改为10.0.0.148,并将目标…

基于Java+SpringMvc+Vue技术的在线学习交流平台的设计与实现---60页论文参考

博主介绍:硕士研究生,专注于Java技术领域开发与管理,以及毕业项目实战✌ 从事基于java BS架构、CS架构、c/c 编程工作近16年,拥有近12年的管理工作经验,拥有较丰富的技术架构思想、较扎实的技术功底和资深的项目管理经…

【PB案例学习笔记】-29制作一个调用帮助文档的小功能

写在前面 这是PB案例学习笔记系列文章的第29篇,该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习,提高编程技巧,以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码,小凡都上传到了gite…

【Spring Boot】关系映射开发(三):多对多映射

《JPA 从入门到精通》系列包含以下文章: Java 持久层 API:JPA认识 JPA 的接口JPA 的查询方式基于 JPA 开发的文章管理系统(CRUD)关系映射开发(一):一对一映射关系映射开发(二&#…

Java_网络编程

网络通信的关键三要素 IP、端口号、协议 IP地址 IP地址(Internet Protocol):全程“互联网协议地址”,是分配给上网设备的唯一标志。 IP地址有两种形式:IPv4、IPv6 InetAddress 代表IP地址 InetAddress 的常用方法…

【算法训练记录——Day42】

Day42——动态规划Ⅳ 1.leetcode_1049最后一块石头的重量II2.leetcode_494目标和3.leetcode_474一和零 1.leetcode_1049最后一块石头的重量II 思路:石头只能用一次。。。怎么才能让碰撞后重量最小呢,还要转换成动态规划,难以理解。。 看题解&…

J024_打印电影的全部信息

一、需求描述 展示多部电影的信息。 电影信息包括:电影名称、电影得分、电影票价格。 二、代码实现 2.1 Movie类 package com.itheima.collection;public class Movie {//电影名称private String name;//电影得分private int score;//电影票价格private double…

【Excel】输入内容自动添加边框线

1. 选中表格区域 → 新建条件规则 2. 设置公式 3. 设置格式 测试生效

[吃瓜教程]南瓜书第6章支持向量机

0.补充知识 0.1 超平面 定义: 超平面是指在𝑛维空间中,维度为 𝑛−1的子空间。它是分割空间的一个平面。 性质: n维空间的超平面 ( w T x b 0 , 其中 w , x ∈ R n ) (w^Tx_b0,其中w,x\in \mathbb R^n) (wTxb​0,其…

C++的set / multiset容器

一、介绍 C的set容器又被称为集合,所有元素在被插入后都会自动排序。 二、数据结构 set / multiset属于关联式容器,底层数据结构是用二叉树实现的。 其余的容器比如vector、deque和list等为序列式容器,因为他们底层使用线性序列结构&#xf…

Windows环境安装Redis和Redis Desktop Manager图文详解教程

版权声明 本文原创作者:谷哥的小弟作者博客地址:http://blog.csdn.net/lfdfhl Redis概述 Redis是一个开源的高性能键值对数据库,以其卓越的读写速度而著称,广泛用于数据库、缓存和消息代理。它主要将数据存储在内存中&#xff0…

CISC和RISC指令集

文章目录 1. 指令集 2. CISC(复杂指令集计算) 3. RISC(精简指令集计算) 4. RISC的设计初衷 5. CISC和RISC流程对比 CISC(复杂指令集计算)的实现 RISC(精简指令集计算)的实现 …

【高中数学之函数】四种幂函数图线(二次、三次、开方、开立方)

【图像】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>UNASSIGNED</title><style type"text/css">.c…

【智能算法应用】灰狼算法求解二维栅格路径规划问题

目录 1.算法原理2.二维路径规划数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】灰狼算法&#xff08;GWO&#xff09;原理及实现 2.二维路径规划数学模型 栅格法模型最早由 W.E. Howden 于 1968 年提出&#xff0c;障碍物的栅格用黑色表示&#xff0c;可通…

基于pi控制的数字锁相环simulink建模与仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 5.算法完整程序工程 1.算法运行效果图预览 (完整程序运行后无水印) 2.算法运行软件版本 matlab2022a 3.部分核心程序 &#xff08;完整版代码包含详细中文注释和操作步骤视频&#xff09…