【问题标题】:error using L-BFGS-B in scipy在 scipy 中使用 L-BFGS-B 时出错
【发布时间】:2013-09-29 20:55:53
【问题描述】:

在 scipy.optimize.minimize 中使用“L-BFGS-B”方法时,我得到了一些令人费解的结果:

import scipy.optimize as optimize
import numpy as np

def testFun():
    prec = 1e3

    func0 = lambda x: (float(x[0]*prec)/prec+0.5)**2+(float(x[1]*prec)/prec-0.3)**2
    func1 = lambda x: (float(round(x[0]*prec))/prec+0.5)**2+(float(round(x[1]*prec))/prec-0.3)**2

    result0 = optimize.minimize(func0, np.array([0,0]), method = 'L-BFGS-B', bounds=((-1,1),(-1,1)))
    print result0
    print 'func0 at [0,0]:',func0([0,0]),'; func0 at [-0.5,0.3]:',func0([-0.5,0.3]),'\n'

    result1 = optimize.minimize(func1, np.array([0,0]), method = 'L-BFGS-B', bounds=((-1,1),(-1,1)))
    print result1
    print 'func1 at [0,0]:',func1([0,0]),'; func1 at [-0.5,0.3]:',func1([-0.5,0.3])

def main():
    testFun()

func0() 和 func1() 是几乎相同的二次函数,输入值的精度差异仅为 0.001。 'L-BFGS-B' 方法适用于 func0。但是,仅仅在func1()中添加一个round()函数,'L-BFGS-B'在第一步之后就停止寻找最优值,直接使用初始值[0,0]作为最优点。

这不仅限于round()。将 func1() 中的 round() 替换为 int() 也会导致同样的错误。

有人知道这是什么原因吗?

非常感谢。

【问题讨论】:

    标签: python optimization scipy


    【解决方案1】:

    BFGS 方法是一种不仅依赖于函数值,还依赖于梯度和 Hessian 的方法(如果您愿意,可以将其视为一阶和二阶导数)。在你的func1() 中,一旦你有round(),渐变不再是连续的。因此,BFGS 方法在第一次迭代后立即失败(可以这样想:BFGS 在起始参数周围搜索,发现梯度没有改变,所以它停止了)。同样,我希望其他需要梯度的方法会像 BGFS 一样失败。

    您可以通过前置条件或重新缩放 X 使其工作。但更好的是,您应该尝试无梯度方法,例如“Nelder-Mead”或“Powell”

    【讨论】:

    • 谢谢朱。所以基本上这是一个局部最小值而不是全局最小值。我对使用“Nelder-Mead”或“Powell”的担忧是他们不能接受约束。最终,我想解决具有线性不等式约束的二维问题。在您看来,Cobyla 是最佳选择吗?
    • 这不是局部最小值与全局最小值的问题。一旦您将破坏导数信息的约束或目标引入行为,则不再保证基于梯度的求解器可以工作,而且很可能不会。正如朱所说,如果您必须在模型中使用诸如 round、int 或 abs 之类的函数,请使用不依赖导数信息的优化器。我所知道的任何优化方法都不能保证在有限时间内达到全局最优。
    • 第二次提交给@Rob Falck。你解释得很好。 OP 的问题本质上是一个离散优化问题,我远非专家。但是对于 OP 来说还有一件事,您使用 'L-BFGS-B' 来设置 bounds 而不是 constrains,这是不同的。我对 Cobyla 的经验有限,无法提出该建议。但是您的f() 很特殊,它>=0,这使得[-1,1] 的bounds 易于实现。 IE。您也许可以使用g=lambda x: (abs(x)>1)*x*x 并优化f(x)*exp(g(x)) 而不是f(x)
    • 谢谢 Rob 和朱。我明白你的意思,关键是func1()的梯度估计可能不准确。朱老师,我的函数不是非负的,所以你说的这个技巧可能不能直接使用。我会想办法的。
    【解决方案2】:

    roundint 创建不可微分的阶跃函数。 l-bfgs-b 方法用于解决平滑优化问题。它使用近似梯度(如果你不给它一个明确的梯度),如果函数有步骤,那将是垃圾。

    【讨论】:

      猜你喜欢
      • 2015-02-19
      • 2017-07-14
      • 2020-09-10
      • 2015-04-18
      • 1970-01-01
      • 2023-04-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多