简体   繁体   English

scipy.optimize.minimize 不会在 maxiter 或回调处停止

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM