迁移学习

在执行黑盒优化时,用户经常运行与之前任务相似的任务。这一观察可以用来加速当前任务。

OpenBox 接收来自 \(K + 1\) 个任务的观测数据作为输入:\(D^1, ..., D^K\) 用于之前的 \(K\) 个任务,\(D^T\) 用于当前任务。到目前为止,OpenBox 仅支持单目标任务之间的迁移学习。支持三种迁移学习算法,分别是 RGPESGPRTransBO

我们提供了一个示例在 examples/transfer_learning.py。 在本教程中,我们将解释如何基于此示例使用迁移学习。

我们首先定义当前任务的目标函数和搜索空间。

import numpy as np
import matplotlib.pyplot as plt
from openbox import Observation, History, Advisor, space as sp, logger

# Define config space
cs = sp.Space()
for i in range(3):
    cs.add_variable(sp.Float('x%d' % (i+1), -200, 200))

# Define objective function
def obj(config):
    x1, x2, x3 = config['x1'], config['x2'], config['x3']
    y = (x1-10)**2 + x2**2 + (x3-100)**2
    return {'objectives': [y]}

然后,我们展示了如何为每个源任务构建一个History类。 我们假设我们已经对一些类似的任务进行了一些观察。 对于每个源任务,我们需要:

  1. 构建Observation

  2. Observation更新到History中。

如果源任务也使用OpenBox进行优化,可以通过optimizer.get_history()获取优化器的历史记录,或通过advisor.get_history()获取顾问的历史记录。

在这种情况下,我们生成一个相关的源任务和两个不相关的源任务。

# Generate history data for transfer learning. transfer_learning_history requires a list of History.
transfer_learning_history = list()  # type: List[History]
# 3 source tasks with 50 evaluations of random configurations each
# one task is relevant to the target task, the other two are irrelevant
num_history_tasks, num_results_per_task = 3, 50
for task_idx in range(num_history_tasks):
    # Build a History class for each source task based on previous observations.
    # If source tasks are also optimized by Openbox, you can get the History by
    # using the APIs from Optimizer or Advisor. E.g., history = advisor.get_history()
    history = History(task_id=f'history{task_idx}', config_space=cs)

    for _ in range(num_results_per_task):
        config = cs.sample_configuration()
        if task_idx == 1:  # relevant task
            y = obj(config)['objectives'][0] + 100
        else:              # irrelevant tasks
            y = np.random.random()
        # build and update observation
        observation = Observation(config=config, objectives=[y])
        history.update_observation(observation)

    transfer_learning_history.append(history)

要开启迁移学习,我们需要指定 transfer_learning_historysurrogate_type

  • transfer_learning_history: 一个History列表,表示来自每个源任务的观察结果。

  • surrogate_type: 一个字符串。与Quick Start中显示的“auto”不同,这里的surrogate_type包括三个部分。

    • 第一部分必须是 "tlbo"

    • 第二部分是迁移学习算法,它们是 "rgpe", "sgpr", 和 "topov3"

    • 第三部分是代理类型,例如 "gp""prf"

    这三个部分用“_”连接。

    使用RGPE作为迁移学习算法和高斯过程作为代理的一个例子是"tlbo_rgpe_gp"

在这里我们定义了一个Advisor,并使用了与examples/ask_and_tell_interface.py中展示的相同API。

你也可以像在快速开始中所示的那样定义一个Optimizer

tlbo_advisor = Advisor(
    config_space=cs,
    num_objectives=1,
    num_constraints=0,
    initial_trials=3,
    transfer_learning_history=transfer_learning_history,  # type: List[History]
    surrogate_type='tlbo_rgpe_gp',
    acq_type='ei',
    acq_optimizer_type='random_scipy',
    task_id='TLBO',
)

max_iter = 20
for i in range(max_iter):
    config = tlbo_advisor.get_suggestion()
    res = obj(config)
    logger.info(f'Iteration {i+1}, result: {res}')
    observation = Observation(config=config, objectives=res['objectives'])
    tlbo_advisor.update_observation(observation)

优化后,我们可以绘制结果。

# show results
history = tlbo_advisor.get_history()
print(history)
history.plot_convergence()
plt.show()