考虑以下简单的MWE:
import numpy as np
from scipy.optimize import direct
def score(x):
parity_in_range = len([v for v in x if 4 <= v <= 6])%3
main_score = np.max(np.abs(np.diff(x)))
return main_score + parity_in_range
length = 20
bounds = [(0,10)] * length
result = direct(score, locally_biased=False, bounds=bounds, maxiter=10000, maxfun=10000)
print(result)
最佳解决方案是使所有参数相等,而不是在4和6之间。例如,所有3。这给出了函数值0。使用scipy的不同优化器,优化的成功程度不同,但使用direct时几乎立即失败。它给出:
message: The volume of the hyperrectangle containing the lowest function value found is below vol_tol=1e-16
success: True
status: 4
fun: 2.0
x: [ 5.000e+00 5.000e+00 ... 5.000e+00 5.000e+00]
nit: 2
nfev: 157
我不确定它是否应该报告成功,但真实的问题是,它在157次功能评估后放弃了那个警告。
有没有办法直接优化这个函数?
1条答案
按热度按时间5uzkadbs1#
终止参数
vol_tol
隐式地取决于问题的维数。搜索空间被划分成一系列超矩形,最小的中间超矩形的大小为(1/3)^n,其中n是维数。当n=20时,这意味着最里面的立方体的体积为2.8e-10。如果最里面的立方体的中点恰好是最低点,那么该立方体将再次细分。由于
vol_tol
默认为1 e-16,这意味着算法将在两次迭代后退出。如果你不想让
vol_tol
导致DIRECT提前退出,你可以将vol_tol
设置为零:运行这个程序,它找到了一个更好的解决方案,尽管仍然不是最优的:
当然,你也可以通过使函数更简单来解决这个问题,例如。使得
parity_in_range
物镜泄漏。改变目标函数为连续
如果一个目标函数是连续的,那么优化这个函数通常会更容易。
在下图中,蓝线表示每个值的现有
parity_in_range
函数,忽略mod 3。橙子线表示一个新函数,它向边缘向下倾斜,提示优化器在该方向有一个较低值。
首先,定义构成此曲线的基本体。我用一个S形函数作为阶跃函数的连续近似。
接下来,我们需要能够移动这个函数的中心,并使sigmoid函数曲线上下移动得更快。
接下来,将奇偶校验函数定义为以4为中心的sigmoid减去以6为中心的sigmoid。强度参数设置为10。
最后,根据该函数定义得分函数。
然后,您可以使用以下代码使用DIRECT来优化此操作。我发现局部偏差使它能够更快地解决它。
通过对目标函数的这种改变,它能够在多达96个维度上解决这个问题。
使用的来源:Lipschitzian Optimization Without the Lipschitz Constant