我刚刚开始使用skopt,所以请随时将我重定向到我可能错过的任何基本教程。不管怎么说,它是这样的:
我有一个优化问题,我通过一个复杂的物理模型计算一个双峰谱,然后提取它的洛伦兹分布(即6个参数,每个峰3个)。然后,我设置了一个成本函数来计算计算参数和实验参数之间的平方差,这样我就得到了一个f(x),它接受一个数组并返回一个标量(如果我理解正确的话,这是gp_minimize需要的)。
我使用以下内容设置了问题的约束:
dim1=Real(name="A1",low=1,high=100) dim2=Real(name="A2",low=1,high=200)
尺寸= dim1、dim2、...但在我的特定系统中,A2是由2*A1绑定的。有没有办法在如上所示的约束中使用它,以避免搜索大量的“非物理”参数空间?在我的特殊情况下,评估模型非常耗时,因此避免不必要的计算将非常有用:)
提前感谢您的帮助!
最好的,克里斯
发布于 2021-11-02 19:20:47
到目前为止,似乎还不可能指定搜索空间维度之间的这种依赖关系。但是,您可以将约束a2 <= 2*a1合并到传递给优化器的目标中。
在下面的示例中,只有在满足约束的情况下,才会计算"true“(且昂贵的)目标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.')

https://stackoverflow.com/questions/67174391
复制相似问题