使用 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
中没有属性 y
和 z
)。您可以获得具有映射名称和优化值的字典,如下所示:
optimized_params = {p.name: res.x[i] for i, p in enumerate(search_space)}
我必须优化一个黑盒问题,它依赖于外部软件(既没有函数定义也没有导数),评估起来非常昂贵。它取决于几个变量,其中一些是实数,另一些是整数。
我认为 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
中没有属性 y
和 z
)。您可以获得具有映射名称和优化值的字典,如下所示:
optimized_params = {p.name: res.x[i] for i, p in enumerate(search_space)}