0

我刚刚开始使用 skopt,所以请随时将我重定向到我可能错过的任何基本教程。无论如何,这里是:

我有一个优化问题,我通过复杂的物理模型计算 2 峰光谱,然后提取其洛伦兹曲线(即 6 个参数,每个峰 3 个)。然后我设置了一个成本函数,计算计算参数和实验参数之间的平方差,这样我得到一个 f(x),它接受一个数组并返回一个标量(如果我理解正确,这就是 gp_minimize 所要求的)。

我使用以下方法设置问题的约束:

暗1=真实(名称=“A1”,低=1,高=100)暗2=真实(名称=“A2”,低=1,高=200)

尺寸 = [dim1, dim2,...] 但在我的特定系统中,A2 受 2*A1 约束。有没有办法在如上所示的约束中使用它,以避免搜索大量“非物理”参数空间?在我的特殊情况下,评估模型非常耗时,因此避免不必要的计算将非常有帮助:)

在此先感谢您的帮助!

最好的,克里斯

4

1 回答 1

0

到目前为止,似乎不可能在搜索空间的维度之间指定这种类型的依赖关系。但是,您可以将约束a2 <= 2*a1合并到传递给优化器的目标中。

f在下面的示例中,仅在满足约束时才评估“真正的”(且昂贵的)目标。否则立即返回一个高值。

在图中,虚线左侧的所有内容都违反了a2 <= 2*a1。红十字是目标 f 的真实最小值,黑点是客观评价。由于该行左侧的目标值较高,因此搜索焦点位于搜索空间的有效部分。当然,在无效子空间中也可能存在评估(在初始随机采样期间或在“探索”而不是“利用”时),但这些不会涉及对昂贵目标的评估f

import numpy as np
from matplotlib import pyplot as plt

from skopt import gp_minimize
from skopt.space import Real
from skopt.utils import use_named_args

# search space
dimensions = [Real(name='a1', low=1, high=10),
              Real(name='a2', low=1, high=10)]


# expensive target function to minimize
def f(a1, a2):
    x1 = a1 - 4.5
    x2 = a2 - 7
    return 1.5*x1**2 + x2**2 - 0.9*x1*x2


# objective function passed to optimizer incorporates constraint
@use_named_args(dimensions)
def objective(a1, a2):

    # if constraint violated quickly return a high value ...
    if a2 > 2*a1:
        return 1e4

    # ... otherwise expensive target can be evaluated
    else:
        return f(a1, a2)


# run optimization
res = gp_minimize(objective, dimensions, n_calls=50, n_initial_points=20, random_state=92)

# evaluate f on regular grid for plotting
a1_grid = np.linspace(0, 10, 50)
a2_grid = np.linspace(0, 10, 50)
f_grid = np.array([f(i, j) for j in a2_grid for i in a1_grid]).reshape(
    len(a1_grid), len(a2_grid))

# visualize results
fig, ax = plt.subplots()
ax.set_xlabel('a1')
ax.set_ylabel('a2')

# contours of f
ax.contourf(a1_grid, a2_grid, f_grid, 20)

# true minimum
ax.plot(4.5, 7, 'rx')

# constraint
ax.plot([0, 5], [0, 10], 'k--')

# evaluations
for x in res.x_iters:
    ax.plot(x[0], x[1], 'k.')

评价

于 2021-11-02T19:20:46.937 回答