Scipy的differential_evolution
(在许多其他优化例程中,例如minimize
)可以声明callback
函数以某种方式提前终止优化。
在StackOverflow上,主要讨论了此callback
,以便在时间限制后停止优化(例如,参见here和here)。
[minimize
和differential_evolution
都处理最小化问题,我的问题是:如果到目前为止找到的最佳目标函数值低于用户定义的值,是否有人知道callback
是否可用于停止优化门槛?
鉴于对此问题缺乏答案和评论,起初我认为这是不可能完成的。因此,我在Scipy的GitHub页面上打开了一个[[enhancement问题,并询问是否要添加此功能。
[其中一位撰稿人结束了我的问题,说尽管采取了棘手的方式(我认为不是很优雅),但可以做到这一点,他给了我一些提示。这是我提出的解决方案,希望对您有所帮助
from scipy.optimize import differential_evolution
from scipy.optimize import rosen
import numpy
class MinimizeStopper(object):
def __init__(self, f=rosen, tau=1):
self.fun = f # set the objective function
self.best_x = None
self.best_func = numpy.inf
self.tau = tau # set the user-desired threshold
def __call__(self, xk, convergence=None, *args, **kwds):
fval = self.fun(xk, *args, **kwds)
if fval < self.best_func:
self.best_func = fval
self.best_x = xk
if self.best_func <= self.tau:
print("Terminating optimization: objective function threshold triggered")
print(self.best_x)
return True
else:
return False
bounds = [(0,2), (0, 2), (0, 2), (0, 2), (0, 2)]
result = differential_evolution(rosen, bounds, callback=MinimizeStopper(), polish=False,disp=True, maxiter=100, popsize=100)
print(result)
返回]
differential_evolution step 1: f(x)= 10.7709 differential_evolution step 2: f(x)= 10.7709 differential_evolution step 3: f(x)= 8.02332 differential_evolution step 4: f(x)= 2.16592 differential_evolution step 5: f(x)= 2.16592 differential_evolution step 6: f(x)= 2.16592 differential_evolution step 7: f(x)= 0.812177 Terminating optimization: objective function threshold triggered [1.01141374 0.95894166 0.91957732 0.87022813 0.70102066] fun: 0.8121773465012827 message: 'callback function requested stop early by returning True' nfev: 4000 nit: 7 success: False x: array([1.01141374, 0.95894166, 0.91957732, 0.87022813, 0.70102066])
一些注意事项:该解决方案不完善,因为它需要对适应度函数进行其他评估才能检查停止标准。不幸的是,由于
scipy.optimize
模块的内部结构,没有解决方法。- 我已经在
rosen
上测试了这种方法,通常,如果目标函数不需要任何其他参数,但是如果目标函数需要其他参数,那么我认为必须使用*args
才能奏效在第二个self.best_x
分支中打印if
不是必须的。我添加的只是调试检查,以查看callback
中是否实际返回了result
找到的最佳解决方案(即differential_evolution()
找到的总体最佳解决方案)