Python Scipy.optimize.l_bfgs_b:为什么它多次计算相同的函数值?

Python Scipy.optimize.l_bfgs_b:为什么它多次计算相同的函数值?,python,scipy,Python,Scipy,我目前正在尝试使用scipy.optimize来找到一个模拟的参数,该模拟试图拟合一些数据。A创建了一个函数,该函数给出了我的模型在数据上的卡方,因此scipy.optimize必须最小化该函数 我的主要问题之一是模拟,因此调用的函数非常耗时,我看到方法L-BFGS_B(或者只是BFGS)在完全相同的点计算函数值的几倍!!!我不明白它为什么会那样做,我快死了 一个非常简单的函数示例: from scipy.optimize import minimize def f3(x): prin

我目前正在尝试使用scipy.optimize来找到一个模拟的参数,该模拟试图拟合一些数据。A创建了一个函数,该函数给出了我的模型在数据上的卡方,因此scipy.optimize必须最小化该函数

我的主要问题之一是模拟,因此调用的函数非常耗时,我看到方法L-BFGS_B(或者只是BFGS)在完全相同的点计算函数值的几倍!!!我不明白它为什么会那样做,我快死了

一个非常简单的函数示例:

from scipy.optimize import minimize

def f3(x):
    print x
    return x[0]*x[0] + x[1]*x[1] + x[2]*x[2]

x0 = [3, -5, 7]

minimize(f3, x0, method = 'L-BFGS-B')
将返回:

[ 3. -5.  7.]
[ 3. -5.  7.]
[ 3.00000001 -5.          7.        ]
[ 3.         -4.99999999  7.        ]
[ 3.         -5.          7.00000001]
[ 2.67070726 -4.45117871  6.23165016]
[ 2.67070726 -4.45117871  6.23165016]
[ 2.67070727 -4.45117871  6.23165016]
[ 2.67070726 -4.4511787   6.23165016]
[ 2.67070726 -4.45117871  6.23165017]
[ -1.72315050e-06   1.66152263e-06  -1.59989476e-06]
[ -1.72315050e-06   1.66152263e-06  -1.59989476e-06]
[ -1.71315050e-06   1.66152263e-06  -1.59989476e-06]
[ -1.72315050e-06   1.67152263e-06  -1.59989476e-06]
[ -1.72315050e-06   1.66152263e-06  -1.58989476e-06]
  status: 0
 success: True
    nfev: 15
     fun: 8.2895683293030033e-12
       x: array([ -1.72315050e-06,   1.66152263e-06,  -1.59989476e-06])
 message: 'CONVERGENCE: NORM_OF_PROJECTED_GRADIENT_<=_PGTOL'
     jac: array([ -3.43630101e-06,   3.33304526e-06,  -3.18978951e-06])
     nit: 2
[3.-5.7]
[ 3. -5.  7.]
[ 3.00000001 -5.          7.        ]
[ 3.         -4.99999999  7.        ]
[ 3.         -5.          7.00000001]
[ 2.67070726 -4.45117871  6.23165016]
[ 2.67070726 -4.45117871  6.23165016]
[ 2.67070727 -4.45117871  6.23165016]
[ 2.67070726 -4.4511787   6.23165016]
[ 2.67070726 -4.45117871  6.23165017]
[-1.72315050e-06 1.66152263e-06-1.59989476e-06]
[-1.72315050e-06 1.66152263e-06-1.59989476e-06]
[-1.71315050e-06 1.66152263e-06-1.59989476e-06]
[-1.72315050e-06 1.67152263e-06-1.59989476e-06]
[-1.72315050e-06 1.66152263e-06-1.58989476e-06]
状态:0
成功:真的
nfev:15
乐趣:8.2895683293030033e-12
x:阵列([-1.72315050e-06,1.66152263e-06,-1.59989476e-06])

信息:“收敛:投影梯度的范数”\up>它正在评估梯度的有限差分近似值。

它会这样做,因为它没有像你希望的那样小心。此缺陷已添加到scipy bug跟踪器中。正如我在那里发布的,您可以通过自己缓存以前的值来解决这个问题。或者,您可以在
minimize
调用中使用
jac=True
,并编写函数以返回点的值和梯度。第一种方法的一个例子是:

import numpy as np
from scipy import optimize

class CacheLast(object):
    def __init__(self, f):
        self.f = f
        self.last_x = None
        self.last_f = None
        self.ncall = 0

    def __call__(self, x):
        if np.all(x == self.last_x):
            return self.last_f
        else:
            self.last_x = x
            self.last_f = self.f(x)
            self.ncall += 1
            return self.last_f

def f3(x):
    return x[0]*x[0] + x[1]*x[1] + x[2]*x[2]

x0 = [3, -5, 7] 

func = CacheLast(f3)
res = optimize.minimize(func, x0, method='L-BFGS-B')

print 'total function calls: ', res.nfev
print 'actual function evals: ', func.ncall
其中:

total function calls:  15
actual function evals:  12

谢谢你的回答,但我仍然想知道为什么它会重新计算完全相同的点,而不使用之前计算的值!重新使用已经计算的值会快得多,特别是在一个耗时的函数的情况下…只是Python 3.2中的一个注释,在标准库中有一个用于此的函数。很好,我不知道。