迁移学习#

在进行黑盒优化时,用户经常运行与以前类似的任务。这个观察可用于加速当前优化任务。

OpenBox 的以 \(K + 1\) 个任务的观测作为输入: \(D^1, ..., D^K\)\(K\) 个先前的任务, \(D^T\) 指当前任务。 目前,OpenBox只支持单目标任务间的迁移学习,并提供了3个迁移学习算法,包括 RGPESGPR, 和 TransBO

我们提供了一个样例程序: 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()从Optimizer中获取历史, 或使用advisor.get_history()从Advisor中获取历史。

在这个例子里,我们生成了一个相关的源任务,和两个不相关的源任务。

# 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的列表,每个History对应一个源任务。

  • surrogate_type: 一个字符串。不同于 快速入门教程 中展示的”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()