[英]scipy.optimize.minimize does not stop at maxiter or callback
I've implemented scipy.optimize.minimize to minimize the mean of delta values of a pandas data frame for a 1D Array with 128 values.我已经实现了 scipy.optimize.minimize 以最小化具有 128 个值的一维数组的 pandas 数据帧的增量值的平均值。
It seems to run and do stuff, but it doesn't stop at maxiter
or at a callback function taken from another Stack Overflow question here.它似乎可以运行并做一些事情,但它不会停止在
maxiter
或从此处的另一个 Stack Overflow 问题中获取的回调函数处。
My code is:我的代码是:
import numpy as np
from scipy.optimize import minimize, rosen
import time
import warnings
class TookTooLong(Warning):
pass
class MinimizeStopper(object):
def __init__(self, max_sec=60*60*5):
self.max_sec = max_sec
self.start = time.time()
def __call__(self, xk=None):
elapsed = time.time() - self.start
if elapsed > self.max_sec:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
else:
# you might want to report other stuff here
print("Elapsed: %.3f sec" % elapsed)
import scipy.optimize
res = scipy.optimize.minimize(minFunct,oned,options=
{"disp":True,"maxiter":100},tol=0.01,
method ="BFGS",callback=MinimizeStopper(1E-3))
The displayed message after some time tells me that maxiter
has been reached and a smaller function value than at the start has been reached, but it just doesn't stop.一段时间后显示的消息告诉我已经达到
maxiter
并且已经达到比开始时更小的函数值,但它并没有停止。 Since it is running in jupyter, I have no way to reach res
without the cell finishing.由于它在 jupyter 中运行,因此如果没有完成单元格,我无法达到
res
。
According to the docs callback should be a callable returning True
for termination and having the following format callback(xk)
.根据文档,回调应该是一个可调用的,返回
True
以终止并具有以下格式callback(xk)
。 Whereas in your code, you are defining it as an initialization of your class.而在您的代码中,您将其定义为类的初始化。 Instead, you should define an instance of your class then assign its
__call__()
function to callback
like the following:相反,您应该定义一个类的实例,然后将其
__call__()
函数分配给callback
,如下所示:
import time
import warnings
import numpy as np
from scipy.optimize import minimize, rosen
class TookTooLong(Warning):
pass
class MinimizeStopper(object):
def __init__(self, max_sec=10):
self.max_sec = max_sec
self.start = time.time()
def __call__(self, xk):
# callback to terminate if max_sec exceeded
elapsed = time.time() - self.start
if elapsed > self.max_sec:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
else:
# you might want to report other stuff here
print("Elapsed: %.3f sec" % elapsed)
# init stopper
minimize_stopper = MinimizeStopper()
# minimze
res = minimize(rosen,
x0 = np.random.randint(5, size=128),
method ="BFGS",
tol = 0.01,
options = {"maxiter":10, "disp":True},
callback = minimize_stopper.__call__)
Alternatively you can define a class for your minimizer and in it build a callback function to terminate your minimization after a certain time.或者,您可以为您的最小化器定义一个类,并在其中构建一个回调函数以在一定时间后终止您的最小化。 This can be done like this:
这可以这样做:
import time
import warnings
import numpy as np
from scipy.optimize import minimize, rosen
class TookTooLong(Warning):
pass
class Minimizer:
def __init__(self, timeout, maxiter):
self.timeout = timeout
self.maxiter = maxiter
def minimize(self):
self.start_time = time.time()
# minimize
res = minimize(rosen,
x0 = np.random.randint(5, size=128),
method ="BFGS",
tol = 0.01,
options = {"maxiter":self.maxiter, "disp":True},
callback = self.callback)
return res
def callback(self, x):
# callback to terminate if max_sec exceeded
elapsed = time.time() - self.start_time
if elapsed > self.timeout:
warnings.warn("Terminating optimization: time limit reached",
TookTooLong)
return True
else:
print("Elapsed: %.3f sec" % elapsed)
# init minimizer and minimize
minimizer = Minimizer(0.1, 100)
result = minimizer.minimize()
Test these code with: timeout=0.1 & maxiter=100
then timeout=10 & maxiter=10
to observe both types of termination.测试这些代码:
timeout=0.1 & maxiter=100
然后timeout=10 & maxiter=10
观察两种类型的终止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.