【问题标题】:How terminate the optimization in scipy?如何终止scipy中的优化?
【发布时间】:2022-01-29 01:53:39
【问题描述】:

我编写了一个具有更多初始猜测值的代码,因此完成优化需要很长时间。虽然几个小时后它几乎会收敛,所以我想停止优化。

res = minimize(f, x0=x0, bounds=bounds,options={'tol': 1e-6,'maxiter':100})

我已经实现了maxiter,但它不起作用,因为迭代次数已经超过并且优化没有停止。所以我想知道maxiter 是如何使用的?我也看到了,作为另一种选择,callback可以用,但是不知道怎么用?所以请帮我解决这些问题。

【问题讨论】:

    标签: python optimization scipy scipy-optimize-minimize


    【解决方案1】:

    scipy.optimize.minimize 中的优化可以通过使用 tolmaxiter 来终止(maxfev 也适用于某些优化方法)。还有一些特定于方法的终止符,如 xtolftolgtol 等,如 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))
    

    【讨论】:

    • 确实我找到了一种在定义的时间内终止优化的方法,但我正在寻找一种在经过一些迭代后终止它的方法。我不知道为什么它不起作用,因为即使我尝试在另一个优化中使用 maxiter,它也没有在那个迭代中停止
    • 您还没有发布minimal reproducible example,所以我也不知道为什么它不起作用。顺便说一句,您还可以使用回调函数通过更改 if 条件if self.nit == desired_iteration 来终止优化,我也在我的答案中添加了这个。另外,尝试打印 x(当前优化的解决方案)和函数的当前值,看看出了什么问题。
    • @sadra 您是否在编辑答案后检查了解决方案?它对你有用吗?
    • Mosin Khan,抱歉迟到了,实际上 maxiter 选项没有再次起作用,但执行时间起作用了
    • 很高兴听到执行时间解决方案有效。如果我的回答解决了您的问题,请查看what should I do when someone answers my question
    猜你喜欢
    • 2022-01-11
    • 2022-06-23
    • 2022-01-24
    • 1970-01-01
    • 2020-08-25
    • 1970-01-01
    • 2012-10-04
    • 2014-07-13
    • 2019-07-19
    相关资源
    最近更新 更多