scipy.minimize中approx_fprime作为jac时迭代为0优化失效问题
Scipy minimize中jac参数使用approx_fprime时优化失效的问题
使用scipy库的minimize函数时遇到异常:当设置jac参数为基于approx_fprime的自定义函数时,迭代次数为0,优化无法正常执行;但将jac参数设置为手动实现的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]
问题原因
核心错误在于fprime的定义:
fprime = lambda x : np.array(approx_fprime(x0, rosen, eps))
这里你始终用初始点x0计算梯度,而不是优化过程中当前迭代的x。也就是说,不管优化算法搜索到哪个点,你传入的梯度都是初始点[1.3, 0.7]的梯度,算法无法根据当前点的梯度方向进行搜索,自然无法推进迭代,直接终止。
你提到“已确认approx_fprime的返回值为ndarray,与rosen_der的返回类型和数值均一致”,但这只是初始点的情况,后续迭代时梯度没有更新,导致算法失效。
修正方案
修改fprime的定义,用当前迭代的x作为approx_fprime的输入参数:
fprime = lambda x : approx_fprime(x, rosen, eps)
或者不用lambda,直接定义函数:
def fprime(x): return approx_fprime(x, rosen, eps)
修正后再运行minimize,算法就能根据当前点的梯度正常迭代优化了。
内容的提问来源于stack exchange,提问作者Jeongmani
相关产品推荐
相关产品推荐

