使用 Scikit Optimize 进行黑盒优化

Black box optimization with Scikit Optimize

我必须优化一个黑盒问题,它依赖于外部软件(既没有函数定义也没有导数),评估起来非常昂贵。它取决于几个变量,其中一些是实数,另一些是整数。

我认为 Scikit Optimize 可能是一个不错的选择。

我想知道以下示例(来自 Scikit Optimize 文档)是否适用于我的实际问题。作为“f”的外部函数提供给定参数集的成本。这是一个虚拟函数,只是为了可重现。但是,与其仅仅依赖于“x”,不如让它依赖于“y”和“z”,它们是其中之一,仅限于整数值。

我看过其他一些面向超参数优化的 Scikit Optimize 的例子(基于 Scikit Learn),但它们对我来说似乎不太清楚。

这是最小的可重现示例(即崩溃):

import numpy as np
from skopt import gp_minimize
from skopt.space import Integer
from skopt.space import Real


np.random.seed(123)
def f(x,y,z):
    return (np.sin(5 * x[0]) * (1 - np.tanh(x[0] ** 2)) *np.random.randn() * 0.1-y[0]**2+z[0]**2)

search_space = list()
search_space.append(Real(-2, 2, name='x'))
search_space.append(Integer(-2, 2, name='y'))
search_space.append(Real(0, 2, name='z'))

res = gp_minimize(f, search_space, n_calls=20)
print("x*=%.2f, y*=%.2f, f(x*,y*)=%.2f" % (res.x[0],res.y[0],res.z[0], res.fun))

致以最诚挚的问候和谢谢

您可以使用 scikit-optimize 中的装饰器函数 use_named_args 将带有名称的搜索 space 传递给成本函数:

import numpy as np
from skopt import gp_minimize
from skopt.space import Integer
from skopt.space import Real
from skopt.utils import use_named_args

np.random.seed(123)

search_space = [
    Real(-2, 2, name='x'),
    Integer(-2, 2, name='y'),
    Real(0, 2, name='z')
    ]

@use_named_args(search_space)
def f(x, y, z):
    return (np.sin(5 * x) * (1 - np.tanh(x ** 2)) *np.random.randn() * 0.1-y**2+z**2)

res = gp_minimize(f, search_space, n_calls=20)

请注意,您的 OptimizeResult res 将优化参数存储在属性 x 中,这是一个最佳值数组。这就是您的代码崩溃的原因(即 res 中没有属性 yz)。您可以获得具有映射名称和优化值的字典,如下所示:

optimized_params = {p.name: res.x[i] for i, p in enumerate(search_space)}