3

在 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() 也会导致相同的错误。

有谁知道这是什么原因?

非常感谢。

4

2 回答 2

11

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

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

于 2013-09-24T15:32:24.633 回答
6

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

于 2013-09-24T15:30:57.143 回答