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

标签 python scipy scipy-optimize-minimize

我实现了 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

最佳答案

根据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 以观察两种类型的终止。

关于python - scipy.optimize.minimize 不会在 maxiter 或回调处停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56252003/

相关文章:

Python:如何将 .txt 文件拆分为两个或多个文件,每个文件的行数相同?

python - 为什么 Sets 允许多个具有不同 hashCode 的相同对象?

python - Django REST框架不解析UTF-8

python - 在python中乘以大型稀疏矩阵

machine-learning - scipy.optimize.minimize 如何取损失函数的导数?

python - 将具有多个自变量和多个参数的函数传递给 scipy optimize minimize

python - 快速问题 : Use the default value of the scipy. optimize.minimize tol 参数

python - 无法安装 PIL

python - 加速 Python 中的列表处理

python - 在 PYTHON 中求解矩阵耦合微分方程时如何绘制特征值?