根据Scipy中目标函数的阈值进行优化

问题描述 投票:0回答:1

Scipy的differential_evolution(在许多其他优化例程中,例如minimize)可以声明callback函数以某种方式提前终止优化。

在StackOverflow上,主要讨论了此callback,以便在时间限制后停止优化(例如,参见herehere)。

[minimizedifferential_evolution都处理最小化问题,我的问题是:如果到目前为止找到的最佳目标函数值低于用户定义的值,是否有人知道callback是否可用于停止优化门槛?

python python-3.x optimization evolutionary-algorithm scipy-optimize
1个回答
0
投票

鉴于对此问题缺乏答案和评论,起初我认为这是不可能完成的。因此,我在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模块的内部结构,没有解决方法。
  1. 我已经在rosen上测试了这种方法,通常,如果目标函数不需要任何其他参数,但是如果目标函数需要其他参数,那么我认为必须使用*args才能奏效在第二个self.best_x分支中打印if不是必须的。我添加的只是调试检查,以查看callback中是否实际返回了result找到的最佳解决方案(即differential_evolution()找到的总体最佳解决方案)
© www.soinside.com 2019 - 2024. All rights reserved.