拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

BayesianOptimization 实战指南:基于高斯过程的 Python 全局优化库从原理到应用

BayesianOptimization 实战指南:基于高斯过程的 Python 全局优化库从原理到应用
  • 机器学习

【免费下载链接】BayesianOptimization

A Python implementation of global optimization with gaussian processes.

项目地址:https://gitcode.com/gh_mirrors/ba/BayesianOptimization
点击查看免费下载

本指南以 README.md 为骨架,结合 bayes_opt 源码(如 bayesian_optimization.py、acquisition.py、target_space.py、parameter.py)及 tests 测试展开,帮助读者掌握安装方法、核心概念、入门流程与进阶能力。

简介

BayesianOptimization 是一个纯 Python 实现的带约束全局优化包,构建于贝叶斯推断和高斯过程(Gaussian Processes, GP)之上,旨在以尽可能少的函数求值次数,找到未知函数的最大值。它尤其适合目标函数求值成本高昂的场景,以及需要**平衡探索(exploration)与利用(exploitation)**的优化问题。读完后你将掌握:从安装、定义目标函数与参数边界,到调用maximize完成优化、读取optimizer.max/optimizer.res结果,再到利用predict、probe、set_bounds等 API 解决真实调参任务的完整能力。

项目概况与定位

本项目是一个 "Pure Python implementation of bayesian global optimization with gaussian processes"(见 bayes_opt/init.py),其核心目标是:

"This is a constrained global optimization package built upon bayesian inference and gaussian processes, that attempts to find the maximum value of an unknown function in as few iterations as possible."

即:在参数空间的有界区域内,用尽量少的采样次数逼近未知函数的最大值。该技术特别适合高成本函数求值和探索/利用平衡重要的场景。

从源码结构看,bayes_opt 包对外暴露的核心组件包括(见init.py):

  • BayesianOptimization:优化器主类,负责调度整个优化循环;
  • TargetSpace:管理优化域(参数边界)并存储已评估的点;
  • ConstraintModel:约束建模;
  • SequentialDomainReductionTransformer:序列域缩减变换器;
  • ScreenLogger:屏幕日志;
  • acquisition:采集函数模块(UCB / EI / POI / ConstantLiar / GPHedge 等)。

当前仓库版本为 3.4.0(见 pyproject.toml),要求 Python >= 3.9,核心依赖包括numpy、scipy、scikit-learn(高斯过程回归器即来自 sklearn)。

安装

README 提供了两种安装方式:

方式一:pip(通过 PyPI)

$ pip install bayesian-optimization

方式二:Conda(通过 conda-forge)

$ conda install -c conda-forge bayesian-optimization

安装后即可通过from bayes_opt import BayesianOptimization使用。开发相关依赖(如 pytest、jupyter、sphinx、ruff 等)可在pyproject.toml的[project.optional-dependencies].dev中找到,可选用pip install -e ".[dev]"安装以便运行测试与文档构建。

工作原理:贝叶斯优化如何用尽可能少的步骤找到最大值

贝叶斯优化的核心思想是:构造一个关于目标函数的后验分布(高斯过程),并基于后验不断决定下一个采样点。

工作流程可以概括为:

  1. 构造先验/后验:用高斯过程(GP)作为目标函数的概率代理模型。随着观测(已采样的点)增多,后验分布逐步改善,算法对参数空间中"哪些区域值得探索、哪些不值得"的把握越来越精确。
  2. 拟合 GP:每一步,将当前已知样本(此前探索过的点)拟合进高斯过程回归器(本项目内部使用sklearn.gaussian_process.GaussianProcessRegressor,默认核为Matern(nu=2.5),见 bayesian_optimization.py)。
  3. 选择下一个点:将后验分布与一种**探索策略(采集函数)**结合,例如 UCB(Upper Confidence Bound,置信上界)或 EI(Expected Improvement,期望改进),来确定下一个值得探索的点。
  4. 代理优化:通过求解采集函数的最大值(一个比原始问题"便宜"得多的代理优化问题)来选取下一个采样点。常用工具即可完成这一步。
  5. 迭代收敛:重复上述过程,逐步逼近全局最优。

上图展示了这一过程的核心可视化:上方面板中,深蓝实线为待优化的真实目标函数,黑色虚线为高斯过程后验预测,红色菱形为已观测点,青绿色区域为 95% 置信区间——置信区间在观测点附近很窄、随距离增大而变宽,直观体现了"已知区域利用、未知区域探索"的权衡;下方面板的效用函数(紫色实线)用于指导下一个采样位置,黄色五角星即"下一个最优猜测点",对应效用函数的最大值点。

反复迭代时,算法会根据对目标函数的已有认知不断平衡探索与利用的需求。这一过程的设计目标就是最小化逼近最优参数组合所需的步骤数。因此,贝叶斯优化最适用于"采样被优化函数非常昂贵"的场景。

项目处于活跃开发中,若遇到问题、发现 bug 或需要修正的地方,可以通过提交 issue 反馈(见 README.md)。

快速上手:一个完整的入门示例

1. 定义要被优化的函数

优化包的第一步且最重要的一步,就是定义待优化的函数。README 中的示例函数如下:

def black_box_function(x, y): """Function with unknown internals we wish to maximize. This is just serving as an example, for all intents and purposes think of the internals of this function, i.e.: the process which generates its output values, as unknown. """ return -x ** 2 - (y - 1) ** 2 + 1

注意(README 声明):我们在这个例子里"恰好"知道函数输出如何依赖参数。真实场景中你并不需要知道——只要有一个函数f,它接受一组已知参数并输出一个实数,即可使用本包。

2. 实例化优化器

实例化BayesianOptimization,指定待优化函数f和带边界的参数空间pbounds。这是一项有约束的优化技术,因此必须为每个参数指定可探测的最小值和最大值:

from bayes_opt import BayesianOptimization # Bounded region of parameter space pbounds = {'x': (2, 4), 'y': (-3, 3)} optimizer = BayesianOptimization( f=black_box_function, pbounds=pbounds, random_state=1, )

BayesianOptimization对象开箱即用,无需太多调参。其主要构造参数(对应 bayesian_optimization.py 中__init__的签名)包括:

参数默认值说明
f必填待最大化的目标函数
pbounds必填字典,键为参数名,值为 (最小值, 最大值) 元组
acquisition_functionNone采集函数;为 None 时,无约束问题默认UpperConfidenceBound(kappa=2.576),有约束问题默认ExpectedImprovement(xi=0.01)
constraintNonescipy.optimize.NonlinearConstraint;约束函数参数名须与f一致
random_stateNone传入 int 作为种子,或传入numpy.random.RandomState;None 时生成未设定种子的随机状态
verbose2日志详细程度
bounds_transformerNone若提供DomainTransformer,将作用于搜索边界
allow_duplicate_pointsFalse为 True 时允许注册重复点(适合高噪声场景),否则重复点会触发NotUniqueError

3. 调用 maximize 执行优化

需要重点了解的核心方法是maximize。它有两个最重要的参数:

  • n_iter:执行多少步贝叶斯优化。步数越多,越有可能找到好的最大值。
  • init_points:执行多少步随机探索。随机探索可以通过多样化探索空间来帮助优化。
optimizer.maximize( init_points=2, n_iter=3, )

运行后屏幕会输出类似下面的迭代日志(README 示例):

| iter | target | x | y | ------------------------------------------------- | 1 | -7.135 | 2.834 | 1.322 | | 2 | -7.78 | 2.0 | -1.186 | | 3 | -19.0 | 4.0 | 3.0 | | 4 | -16.3 | 2.378 | -2.413 | | 5 | -4.441 | 2.105 | -0.005822 | =================================================

从源码看,maximize的默认参数为init_points=5, n_iter=25(见 bayesian_optimization.py)。其执行逻辑是:先用随机点"预热"队列(_prime_queue),随后循环——若队列非空则从队列取出探测点(由probe(lazy=True)预先放入),否则调用suggest()让采集函数给出下一个建议点;若配置了bounds_transformer,则在真正的迭代轮次之后调用set_bounds更新边界(详见 maximize 实现)。

4. 读取优化结果

找到的最佳参数组合与目标值,通过属性optimizer.max访问:

print(optimizer.max) >>> {'target': -4.441293113411222, 'params': {'y': -0.005822117636089974, 'x': 2.104665051994087}}

所有被探测的参数及对应的目标值,通过属性optimizer.res访问:

for i, res in enumerate(optimizer.res): print("Iteration {}: \n\t{}".format(i, res)) >>> Iteration 0: >>> {'target': -7.135455292718879, 'params': {'y': 1.3219469606529488, 'x': 2.8340440094051482}} >>> Iteration 1: >>> {'target': -7.779531005607566, 'params': {'y': -1.1860045642089614, 'x': 2.0002287496346898}} >>> Iteration 2: >>> {'target': -19.0, 'params': {'y': 3.0, 'x': 4.0}} >>> Iteration 3: >>> {'target': -16.29839645063864, 'params': {'y': -2.412527795983739, 'x': 2.3776144540856503}} >>> Iteration 4: >>> {'target': -4.441293113411222, 'params': {'y': -0.005822117636089974, 'x': 2.104665051994087}}

max与res最终都委托给TargetSpace(见 target_space.py):max()返回{'target': ..., 'params': {...}}字典,在有约束时还会附带constraint键;res()返回每条记录的字典列表,有约束时每条记录还会包含constraint与allowed字段。

进阶 API:从"黑盒自动优化"走向"可控的优化流程"

除maximize外,BayesianOptimization还提供若干可组合的底层 API(均见 bayesian_optimization.py):

  • register(params, target, constraint_value=None):直接注册一个已知目标值的观测点(不调用目标函数)。测试用例 test_register 对其进行了覆盖。
  • probe(params, lazy=True):在给定点评估函数。lazy=True时点被放入队列,待调用maximize()时评估;lazy=False时立即评估。对应测试见 test_probe_lazy 与 test_probe_eager。
  • suggest():让采集函数建议下一个值得探测的点(无观测时退化为随机采样),可配合probe实现自定义优化循环。
  • predict(params, return_std=False, return_cov=False, fit_gp=True):在给定参数处预测目标函数值,可返回预测标准差/协方差;return_std与return_cov不能同时为 True;fit_gp=True时预测前会重新拟合内部 GP(观测数为 0 时会抛出RuntimeError,可设置fit_gp=False使用 GP 先验进行预测)。
  • set_bounds(new_bounds):修改搜索空间的边界(字典:参数名 → 新边界)。
  • set_gp_params(**params):设置内部GaussianProcessRegressor的参数;若传kernel,会自动用wrap_kernel包装以兼容参数类型变换(见 parameter.py)。
  • random_sample(n=1):从目标空间随机采样参数。
  • save_state(path)/load_state(path):将优化器完整状态保存为 JSON 或从中恢复,便于断点续跑;状态涵盖 pbounds、已注册点、目标值、约束值、GP 参数、随机状态、采集函数参数等(见 保存/加载实现)。

提示(源码说明):maximize循环只在"基于采集函数建议新点"时拟合 GP,因此循环结束时 GP 可能并未在所有已注册点上完成拟合。若打算在优化结束后使用 GP 模型,请记得调用predict(..., fit_gp=True)显式拟合(见 maximize 的 Warning 说明)。

参数类型:不只有浮点数

pbounds不仅支持连续浮点参数。从 parameter.py 与 target_space.py 的make_params逻辑可以看出,参数被解析为三类:

  • 浮点参数(FloatParameter):pbounds中给出二元数值元组(或(min, max, float)三元组),在浮点空间中连续采样,核变换为恒等。
  • 整数参数(IntParameter):(min, max, int)三元组;采样用randint,kernel_transform会四舍五入取整。
  • 类别参数(CategoricalParameter):pbounds中直接给出候选值列表(如['red', 'blue', 'green']);内部以 one-hot 编码参与 GP 计算,采样时随机选取类别(见 CategoricalParameter)。

源码在检测到非浮点参数时会发出警告:"Non-float parameters are experimental and may not work as expected.",提示该类参数属于实验性功能。整数与类别参数的优化方法见 README 中的引用文献 Garrido-Merchán & Hernández-Lobato 的工作。

采集函数:调节探索与利用的天平

采集函数(Acquisition Function)是"决定下一步探测哪里"的核心。模块位于 acquisition.py,README 明确提及 UCB 与 EI 两种,完整实现还包括 POI、ConstantLiar、GPHedge。

基础采集函数

  • UpperConfidenceBound(UCB):UCB(x) = μ(x) + κ·σ(x)。参数kappa(默认 2.576)控制探索/利用权衡:越小越倾向利用(exploitation),越大越倾向探索(exploration)。还支持exploration_decay(衰减率,默认 None 不衰减)与exploration_decay_delay(延迟轮数)实现 kappa 的逐步衰减(decay_exploration)。无约束问题默认使用它。
  • ProbabilityOfImprovement(POI):POI(x) = Φ((μ(x) - y_max - ξ)/σ(x)),其中 Φ 为标准正态 CDF,ξ 控制探索/利用权衡(越小越倾向利用)。
  • ExpectedImprovement(EI):在 POI 基础上还考虑改进幅度:EI(x) = (μ(x)-y_max-ξ)·Φ(...) + σ(x)·φ(...),φ 为正态 PDF。有约束问题默认使用它(默认xi=0.01)。

元采集函数(Meta Acquisition Functions)

  • ConstantLiar:用于异步/并行优化。它在目标空间的副本上注册"假想点"(dummy points,取值可为固定浮点数或'min'/'mean'/'max'策略),从而降低 GP 在"已被建议但尚未评估"的点附近的方差,避免多个 worker 重复建议同一点(详见 ConstantLiar 实现)。
  • GPHedge:一个元采集函数,维护多个基础采集函数的"累积收益"(gains),每一步用 softmax 加权从各基础采集函数的建议中选出一个候选点(基于 Brochu 等人的 portfolio allocation 思想,详见 GPHedge)。

每个采集函数均可通过BayesianOptimization(acquisition_function=...)传入。AcquisitionFunction是基类,你可以通过继承它实现自定义采集函数。

建议点的求解:随机采样 + 智能优化

suggest()使用"随机采样(廉价)+ 智能优化(昂贵但更准)"两段式策略(见 acquisition.py 的_acq_min):

  1. 在参数空间随机采样n_random(默认 10,000)个点,计算采集函数值,取最优者;同时选出n_smart(默认 10)个最优样本作为智能优化器的起点。
  2. 若所有参数都是连续型,用 L-BFGS-B 从这些起点出发做局部优化;若存在离散参数,则改用差分进化(differential evolution)并配合连续维度的确定性搜索细化结果。

带约束的优化

本项目定位是"constrained global optimization"。在构造优化器时可通过scipy.optimize.NonlinearConstraint传入约束(约束函数参数名须与目标函数一致):

from scipy.optimize import NonlinearConstraint # 示例:要求 x + y 不小于 0(约束函数与目标函数同名参数) def constraint_function(x, y): return x + y optimizer = BayesianOptimization( f=black_box_function, pbounds=pbounds, constraint=NonlinearConstraint(constraint_function, lb=0, ub=np.inf), )

从 constraint.py 看,约束由ConstraintModel用独立的 GP 建模:对每个约束分别拟合 GP,计算约束满足概率p = Pr{c_low ≤ c̃(x) ≤ c_up}(多个约束时假设条件独立,联合概率为各概率之积)。在建议新点时,采集函数会乘以约束满足概率,从而偏向满足约束的区域;TargetSpace.max()也只返回满足约束与边界条件的最优点(见 target_space.py 的mask逻辑)。注意 UCB 与 ConstantLiar 不支持约束(会抛ConstraintNotSupportedError),有约束时默认改用 EI。

README 中提供了约束优化的引用文献 Gardner et al. (2014) "Bayesian optimization with inequality constraints"。

域缩减:SequentialDomainReductionTransformer

对于高维或边界设计空间大的问题,可使用SequentialDomainReductionTransformer(见 domain_reduction.py)逐步收缩搜索窗口,加速收敛。用法:

from bayes_opt import BayesianOptimization, SequentialDomainReductionTransformer bounds_transformer = SequentialDomainReductionTransformer() optimizer = BayesianOptimization( f=black_box_function, pbounds=pbounds, random_state=1, bounds_transformer=bounds_transformer, )

其核心参数(README 引用 Stander & Craig (2002) 的域缩减方案):

  • gamma_osc(默认 0.7):用于缩放(通常是抑制)振荡的参数;
  • gamma_pan(默认 1.0):用于缩放(通常为单位化)平移的参数;
  • eta(默认 0.9):缩放参数,用于收缩关注区域;
  • minimum_window(默认 0.0):每个参数的最小窗口宽度(可为标量、数组或按参数名的字典)。

从源码看,其每次变换以当前最优点为中心、以收缩率缩放后的窗口半径构造新边界,并通过_trim确保新边界不超出全局边界、不小于最小窗口(超出部分会被重置并给出警告,见 domain_reduction.py)。注意:域缩减仅支持全浮点参数,若存在非 FloatParameter 会抛出 ValueError(见initialize)。README 提供了对应的引用文献。

输出与日志

BayesianOptimization默认使用ScreenLogger(verbose 级别 2),在控制台输出迭代表格。ScreenLogger同样由bayes_opt.logger导出(见init.py),并支持自定义 logger 以对接自己的日志体系。

引用

若在你的研究中使用了本包,请按如下格式引用(详见 README.md):

@Misc{, author = {Fernando Nogueira}, title = {{Bayesian Optimization}: Open source constrained global optimization tool for {Python}}, year = {2014--}, url = " https://github.com/bayesian-optimization/BayesianOptimization" }

若使用了以下高级功能,请额外引用相应文献:

  • SequentialDomainTransformer:Stander, Nielen and Craig, Kenneth (2002). "On the robustness of a simple domain reduction scheme for simulation-based optimization". Engineering Computations, 19.
  • 约束优化:Gardner, Jacob R et al. (2014). "Bayesian optimization with inequality constraints." ICML 2014, pp. 937–945.
  • 非浮点参数优化:Garrido-Merchán, Eduardo C and Hernández-Lobato, Daniel (2020). "Dealing with categorical and integer-valued variables in bayesian optimization with gaussian processes". Neurocomputing, 380, pp. 20–35.

进一步探索

本仓库提供了丰富的示例与测试,可继续深入:

  • Notebook 示例:见 examples 目录,包括 basic-tour.ipynb(入门)、advanced-tour.ipynb(进阶)、acquisition_functions.ipynb(采集函数)、constraints.ipynb(约束)、domain_reduction.ipynb(域缩减)、parameter_types.ipynb(参数类型)、async_optimization.py(异步优化)等。
  • 脚本示例:如 sklearn_example.py(配合 scikit-learn 的超参调优)、typed_hyperparameter_tuning.py、duplicate_point.py(重复点处理)。
  • 测试用例:见 tests,如 test_bayesian_optimization.py、test_acquisition.py、test_constraint.py、test_target_space.py、test_seq_domain_red.py,可用于验证各 API 行为与边界条件。
  • 文档源码:见 docsrc(Sphinx 文档),其中 reference 提供了各模块的 API 参考。

结语

BayesianOptimization 用"高斯过程代理模型 + 采集函数"的组合,把昂贵函数的全局最大化压缩到极少的求值次数内。掌握maximize、probe、suggest、predict这套 API,再配合采集函数选择、约束建模与域缩减,你就能在机器学习超参调优、仿真优化等高成本场景中快速落地这套贝叶斯优化流程。

  • 机器学习

【免费下载链接】BayesianOptimization

A Python implementation of global optimization with gaussian processes.

项目地址:https://gitcode.com/gh_mirrors/ba/BayesianOptimization
点击查看免费下载

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表