scipy.optimize.minimize 中的优化可以通过使用 tol 和 maxiter 来终止(maxfev 也适用于某些优化方法)。还有一些特定于方法的终止符,如 xtol、ftol、gtol 等,如 scipy.optimize.minimize documentation page 中所述.还提到如果您不提供方法,则根据问题使用BFGS、L-BFGS-B或SLSQP。
关于您的第一个问题,您正在以正确的方式使用 maxiter 选项,但我不能说明为什么它没有被强制执行,因为您没有提供 MWE。但是 tol 选项放在 options 括号内,这是错误的,应该在它之外,比如:
res = minimize(f, x0=x0, bounds=bounds, tol=1e-6,options={'maxiter':100})
我的建议是在上述 scipy.optimize.minimize 文档页面上查找针对您的问题的优化方法,并使用特定的容差选项。
关于你的第二个问题,如果你想在一段时间后终止优化,你可以做如下事情,这是受SuperKogito提出的this解决方案的启发:
from time import time
import warnings
from scipy.optimize import minimize
class TookTooLong(Warning):
pass
class optimizer():
def __init__(self, maxtime_sec):
self.nit = 0
self.maxtime_sec = maxtime_sec
# def fun(self, *args):
# define your function to be minimized here
def callback(self, x):
# callback to terminate if maxtime_sec is exceeded
self.nit += 1
elapsed_time = time() - self.start_time
if elapsed_time > self.maxtime_sec:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
else:
# you could print elapsed iterations and time
print("Elapsed: %.3f sec" % elapsed_time)
print("Elapsed iterations: ", self.nit)
def optimize(self):
self.start_time = time()
# set your initial guess to 'x0'
# set your bounds to 'bounds'
opt = minimize(self.fun, x0=x0, bounds=bounds,
callback=self.callback, tol=1e-6,options={'maxiter':100})
return opt
# set maxtime_sec variable to desired stopping time
maxtime_sec = 100
op = optimizer(maxtime_sec)
res = op.optimize()
print(res)
您还可以在所需的迭代之后使用 回调 停止优化。然而,这并不优雅。只需将上面代码中的callback函数改成如下:
class TookTooManyIters(Warning):
pass
class optimizer():
def __init__(self, maxtime_sec):
self.nit = 0
self.maxtime_sec = maxtime_sec
# def fun(self, *args):
# define your function to be minimized here
def callback(self, x):
# callback to terminate if desired_iteration is reached
self.nit += 1
desired_iteration = 10 # for example you want it to stop after 10 iterations
if self.nit == desired_iteration:
warnings.warn("Terminating optimization: iteration limit reached",
TookTooManyIters)
else:
# you could print elapsed iterations, current solution
# and current function value
print("Elapsed iterations: ", self.nit)
print("Current solution: ", x)
print("Current function value: ", self.fun(x))