# 并行和分布式验证 大多数贝叶斯优化方法(BO)只对搜索空间进行串行的探索。 为了充分利用并行设施中的计算资源,**OpenBox**提出了一种分布式并行化的机制。 在这种机制中,多个配置可以在多个worker上并发地被验证。 我们考虑了两种并行机制: 1) **同步并行(左)**:每个worker从推荐配置中选择一个配置进行验证。直到所有worker都完成这一轮的验证后再开始下一轮验证。 2) **异步并行(右)**:每个worker从推荐配置中选择一个配置进行验证。对于每个worker,当前的验证结束后就立刻开始下一轮验证。 **OpenBox** 实现了一种基于局部惩罚的并行化机制。其目标是对有前途的新配置进行采样,这个采样要与其它worker正在验证的配置相差足够远。 这种机制可以处理众所周知的exploration与exploitation之间的权衡,同时防止工人探索类似的配置。 在本教程中,我们将演示如何使用**OpenBox**在本地计算机上以并行的方式解决优化问题。 ## 问题描述 首先,定义搜索的**搜索空间**和想要**最小化**的**目标函数**。这里我们使用**Branin**函数。 ```python 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]} ``` 如果你对这个问题描述还不熟悉,请参考我们的{ref}`快速入门教程 `。 ## 单机并行验证 这里我们使用 **ParallelOptimizer** 来以并行的方式在单机上优化目标函数。 ```python 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())** 来打印优化结果: ```python print(opt.get_history()) ``` ``` +----------------------------------------------+ | Parameters | Optimal Value | +-------------------------+--------------------+ | x1 | -3.138286 | | x2 | 12.292733 | +-------------------------+--------------------+ | Optimal Objective Value | 0.3985991718620365 | +-------------------------+--------------------+ | Num Configs | 100 | +-------------------------+--------------------+ ``` ## 分布式并行验证 **OpenBox** 提供了一个便捷的方式执行分布式并行验证。 首先,在主节点上启动优化器**DistributedOptimizer**。 这里我们仍使用前面定义的Branin函数作为目标函数。 ```python 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**。 ```python from openbox import DistributedWorker worker = DistributedWorker(branin, ip="127.0.0.1", port=13579, authkey=b'abc') worker.run() ``` 在优化完成后, 在主节点上调用 **print(opt.get_history())** 来打印优化结果: ```python print(opt.get_history()) ``` ``` +----------------------------------------------+ | Parameters | Optimal Value | +-------------------------+--------------------+ | x1 | -3.138286 | | x2 | 12.292733 | +-------------------------+--------------------+ | Optimal Objective Value | 0.3985991718620365 | +-------------------------+--------------------+ | Num Configs | 100 | +-------------------------+--------------------+ ```