并行和分布式验证#
大多数贝叶斯优化方法(BO)只对搜索空间进行串行的探索。 为了充分利用并行设施中的计算资源,OpenBox提出了一种分布式并行化的机制。 在这种机制中,多个配置可以在多个worker上并发地被验证。
我们考虑了两种并行机制:
同步并行(左):每个worker从推荐配置中选择一个配置进行验证。直到所有worker都完成这一轮的验证后再开始下一轮验证。
异步并行(右):每个worker从推荐配置中选择一个配置进行验证。对于每个worker,当前的验证结束后就立刻开始下一轮验证。
OpenBox 实现了一种基于局部惩罚的并行化机制。其目标是对有前途的新配置进行采样,这个采样要与其它worker正在验证的配置相差足够远。 这种机制可以处理众所周知的exploration与exploitation之间的权衡,同时防止工人探索类似的配置。
在本教程中,我们将演示如何使用OpenBox在本地计算机上以并行的方式解决优化问题。
问题描述#
首先,定义搜索的搜索空间和想要最小化的目标函数。这里我们使用Branin函数。
import numpy as np
from openbox import space as sp
# Define Search Space
space = sp.Space()
x1 = sp.Real("x1", -5, 10, default_value=0)
x2 = sp.Real("x2", 0, 15, default_value=0)
space.add_variables([x1, x2])
# Define Objective Function
def branin(config):
x1, x2 = config['x1'], config['x2']
y = (x2 - 5.1 / (4 * np.pi ** 2) * x1 ** 2 + 5 / np.pi * x1 - 6) ** 2 \
+ 10 * (1 - 1 / (8 * np.pi)) * np.cos(x1) + 10
return {'objectives': [y]}
如果你对这个问题描述还不熟悉,请参考我们的快速入门教程。
单机并行验证#
这里我们使用 ParallelOptimizer 来以并行的方式在单机上优化目标函数。
from openbox import ParallelOptimizer
# Parallel Evaluation on Local Machine
opt = ParallelOptimizer(
branin,
space,
parallel_strategy='async',
batch_size=4,
batch_strategy='default',
num_objectives=1,
num_constraints=0,
max_runs=50,
surrogate_type='gp',
task_id='parallel_async',
)
history = opt.run()
除了被传递给 ParallelOptimizer 的 目标函数 和 搜索空间,其它的参数有:
parallel_strategy=‘async’ / ‘sync’ 设置并行验证是异步的还是同步的。 我们推荐使用 ‘async’ 异步并行方式,因为它能更充分地利用资源,减少空闲。 实验表明异步并行相比 ‘sync’ 同步并行达到了更好的性能。
batch_size=4 设置并行worker的数量。
batch_strategy=‘default’ 设置如何同时提出多个建议的策略。 我们推荐使用默认参数 ‘default’ 来获取稳定的性能。
num_objectives=1 和 num_constraints=0 表明我们的函数返回一个没有约束的单目标值。
max_runs=100 表明优化过程循环100次 (优化目标函数100次).
surrogate_type=‘gp’ 对于数学问题,我们推荐使用高斯过程(‘gp’)作为贝叶斯优化的替代模型。 对于实际问题,比如超参数优化(HPO),我们推荐使用随机森林(‘prf’)。
task_id 指明优化任务名称。
在优化完成后, 调用 print(opt.get_history()) 来打印优化结果:
print(opt.get_history())
+----------------------------------------------+
| Parameters | Optimal Value |
+-------------------------+--------------------+
| x1 | -3.138286 |
| x2 | 12.292733 |
+-------------------------+--------------------+
| Optimal Objective Value | 0.3985991718620365 |
+-------------------------+--------------------+
| Num Configs | 100 |
+-------------------------+--------------------+
分布式并行验证#
OpenBox 提供了一个便捷的方式执行分布式并行验证。
首先,在主节点上启动优化器DistributedOptimizer。 这里我们仍使用前面定义的Branin函数作为目标函数。
from openbox import DistributedOptimizer
from openbox.utils.platform import get_platform
# Distributed Evaluation
n_workers = 4
ip = "127.0.0.1" if get_platform() == 'Windows' else ''
opt = DistributedOptimizer(
branin,
space,
parallel_strategy='async',
batch_size=n_workers,
batch_strategy='default',
num_objectives=1,
num_constraints=0,
max_runs=50,
surrogate_type='gp',
task_id='distributed_opt',
ip=ip,
port=13579,
authkey=b'abc',
)
history = opt.run()
除了被传递给 ParallelOptimizer 的 目标函数 和 搜索空间,其它的参数有:
port: 主节点上优化器的网络端口号。
authkey: worker连接主节点优化器所需的授权秘钥。
parallel_strategy=‘async’ / ‘sync’ 设置并行验证是同步的还是异步的。 我们推荐使用 ‘async’ 因为它能更充分地利用资源,并比 ‘sync’ 实现了更好的性能。
batch_size=4 设置并行worker的数量。
batch_strategy=‘default’ 设置如何同时提出多个建议的策略。 我们推荐使用默认参数 ‘default’ 来获取稳定的性能。
num_objectives=1 和 num_constraints=0 表明我们的函数返回一个没有约束的单目标值。
max_runs=100 表明优化过程循环100次 (优化目标函数100次).
surrogate_type=‘gp’ 对于数学问题,我们推荐使用高斯过程(‘gp’)作为贝叶斯优化的替代模型。 对于实际问题,比如超参数优化(HPO),我们推荐使用随机森林(‘prf’)。
task_id 指明优化任务名称。
接下来,启动worker节点以从主节点接收参数配置,并执行验证。 除了目标函数,在启动worker时还需要指定主节点ip, 端口号port和授权秘钥authkey。
from openbox import DistributedWorker
worker = DistributedWorker(branin, ip="127.0.0.1", port=13579, authkey=b'abc')
worker.run()
在优化完成后, 在主节点上调用 print(opt.get_history()) 来打印优化结果:
print(opt.get_history())
+----------------------------------------------+
| Parameters | Optimal Value |
+-------------------------+--------------------+
| x1 | -3.138286 |
| x2 | 12.292733 |
+-------------------------+--------------------+
| Optimal Objective Value | 0.3985991718620365 |
+-------------------------+--------------------+
| Num Configs | 100 |
+-------------------------+--------------------+