我尝试在scipy包中使用最小化函数,如下面的代码所示当我使用jac option = approx_fprime
时,迭代为0,优化不起作用。但是当我使用jac option = rosen_der
时,它工作了!
import numpy as np
from scipy.optimize import minimize, approx_fprime
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
def rosen_der(x):
# derivative of rosenbrock function
xm = x[1:-1]
xm_m1 = x[:-2]
xm_p1 = x[2:]
der = np.zeros_like(x)
der[1:-1] = 200*(xm-xm_m1**2) - 400*(xm_p1 - xm**2)*xm - 2*(1-xm)
der[0] = -400*x[0]*(x[1]-x[0]**2) - 2*(1-x[0])
der[-1] = 200*(x[-1]-x[-2]**2)
return der
x0=np.array([1.3, 0.7])
eps = np.sqrt(np.finfo(float).eps)
fprime = lambda x : np.array(approx_fprime(x0, rosen, eps))
res = minimize(rosen, x0, method='CG', jac=fprime, options={'maxiter':10, 'disp': True})
print(res.x)
[ 515.40001106 -197.99999905]
[ 515.4 -198. ]
98.10000000000005
Warning: Desired error not necessarily achieved due to precision loss.
Current function value: 98.100000
Iterations: 0
Function evaluations: 33
Gradient evaluations: 21
[1.3 0.7]
我检查了approx_fprime是narray,相同的rosen_der和值也是相同的。为什么优化不起作用?
你的函数fprime
是x
的函数,但近似于x0
的导数。因此,在每次迭代中,您都在初始猜测x0
处评估梯度。你应该在x
处计算/近似导数:
fprime = lambda x : approx_fprime(x, rosen, eps)
注意approx_fprime
已经返回了一个np。narray,所以不需要额外的np。数组调用。
同样值得一提的是,你不需要传递近似的导数,因为minimize
在默认情况下是通过有限差分来近似它们的,一旦你不传递任何导数,即jac=None
。然而,minimize
在底层使用approx_derivative
而不是approx_fprime,因为它提供了在可变边界上求导数的支持。