【问题标题】:Setting convergence criteria for scipy.optimize.fmin (and others)为 scipy.optimize.fmin (和其他)设置收敛标准
【发布时间】:2015-05-21 14:31:05
【问题描述】:

我正在进行一项优化任务,其中成本函数评估非常昂贵,并且可以容忍一些错误。我正在使用 scipy.optimize 中的一些预先打包的 scipy 方法来开始。我正在使用的第一个是 fmin,它实现了 nelder mead 单纯形算法。

此函数有两个与收敛相关的参数 xtol 和 ftol,它们 (as I understand it) 指定了一个收敛标准,如果 x 或 f(参数集和成本分别)在迭代中变化小于 xtol 或 ftol,函数返回。

但是,由于成本函数对我来说非常昂贵,我还希望能够指定一个成本阈值,如果它找到一个成本低于阈值的点,它将立即返回。

是否可以为 scipy.optimize.fmin 指定此阈值?

额外问题:我没有详细研究过许多其他方法,但看起来这些阈值选项也不存在。这是 scipy 优化方法的典型特征吗?尝试贡献这个功能对我来说有价值吗?

【问题讨论】:

    标签: python numpy optimization scipy


    【解决方案1】:

    对于可以表示为x 的函数的任何标准,都可以停止迭代。这里的想法是劫持callback 方法并使用异常进行流控制。以下是利用此想法的两种解决方案:

    from scipy.optimize import fmin_bfgs
    import numpy as np
    f = lambda x: np.linalg.norm(x**2)
    x0 = np.random.rand(100)
    

    解决方案 1:

    global result
    
    class SmallEnoughException(Exception):
        pass
    
    def check_conv_criteria(xk):
        global result
        if np.linalg.norm(xk) < 0.1:
            result = xk
            raise SmallEnoughException()
    
    try:
        x, _, _ = fmin_bfgs(f, x0, callback=check_conv_criteria)
    except SmallEnoughException:
        x = result
    

    解决方案 2:

    class StopOptimizingException(Exception):
        pass
    
    class CallbackCollector:
    
        def __init__(self, f, thresh):
            self._f  = f
            self._thresh = thresh
    
        def __call__(self, xk):
            if self._f(xk) < self._thresh:
                self.x_opt = xk
                raise StopOptimizingException()
    
    try:
        cb = CallbackCollector(f, thresh=0.2)
        x, _, _ = fmin_bfgs(f, x0, callback=cb)
    except StopOptimizingException:
        x = cb.x_opt
    

    【讨论】:

    • 这不会迫使人们评估每个回调的成本函数吗?打破了提前停止的目的,试图减少调用成本函数的次数。
    • @Jyan - 是的,但我看不到解决办法。我想在某些时候您必须计算f(x) 才能将其与阈值进行比较。你有什么办法可以避免这种情况吗?如果f(x) 将被计算多次,您可以通过缓存函数的评估来显着提高。
    • 是的,我意识到我的评论有点愚蠢。我实际上认为解决这个问题的最好方法是将停止标准放在成本函数中,这样当成本函数在一个成本足够低的点上进行评估时,它会引发异常——无需使用回调。感谢您的想法。
    猜你喜欢
    • 2020-04-29
    • 2016-01-25
    • 1970-01-01
    • 2018-07-28
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多