【问题标题】:scipy.optimize.minimize does not stop at maxiter or callbackscipy.optimize.minimize 不会在 maxiter 或回调处停止
【发布时间】:2019-05-22 08:02:32
【问题描述】:

我已经实现了 scipy.optimize.minimize 以最小化具有 128 个值的一维数组的 pandas 数据帧的增量值的平均值。

它似乎在运行并做一些事情,但它并没有停止在 maxiter 或从此处的另一个 Stack Overflow 问题获取的回调函数处。

我的代码是:

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))

一段时间后显示的消息告诉我已达到maxiter,并且已达到比开始时更小的函数值,但它并没有停止。由于它是在 jupyter 中运行的,因此如果没有完成单元格,我无法到达 res

【问题讨论】:

    标签: python scipy scipy-optimize-minimize


    【解决方案1】:

    根据docs 回调应该是一个可调用的返回True 用于终止并具有以下格式callback(xk)。而在您的代码中,您将其定义为类的初始化。相反,您应该定义一个类的实例,然后将其 __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__)
    

    或者,您可以为您的最小化器定义一个类,并在其中构建一个回调函数以在一定时间后终止您的最小化。这可以像这样完成:

    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()
    

    测试这些代码:timeout=0.1 & maxiter=100 然后timeout=10 & maxiter=10 观察这两种终止类型。

    【讨论】:

      猜你喜欢
      • 2020-10-05
      • 2023-03-12
      • 2018-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-06-30
      • 2010-11-25
      • 2011-07-14
      相关资源
      最近更新 更多