使用sp.optimize.minimize时目标函数与雅可比矩阵的参数适配问题
解决scipy.optimize.minimize中目标函数与雅可比参数不一致的问题
这确实是scipy.optimize.minimize里一个常见的小细节坑——它默认会把args参数中的所有值同时传递给目标函数和雅可比函数,不管后者是否需要这些参数。不过不用被迫修改雅可比函数去忽略无用参数,有几种更优雅的解决方案:
方案1:用Lambda函数包装雅可比,过滤多余参数
这是最简洁直观的方法,通过lambda函数接收minimize传递的所有参数,只把雅可比需要的部分传给原J函数:
import numpy as np from scipy import optimize def f(x, y, z): return x**2 + x*y**3 + z def J(x, y): return 2*x + y**3 x0, y, z = 0, 1, 4 # Lambda接收x和args里的所有参数,只将x和y传给J result = optimize.minimize( f, x0, args=(y, z), jac=lambda x, *args: J(x, args[0]) # args[0]就是传入的y,忽略args[1]的z ) print(result)
这里的*args会捕获minimize传递的y和z,我们只取第一个元素(也就是y)传给J,完美匹配原函数的参数要求。
方案2:用functools.partial封装雅可比函数
如果你觉得lambda的可读性不够,也可以用functools.partial来固定雅可比需要的参数,同时忽略多余的输入:
import numpy as np from scipy import optimize from functools import partial def f(x, y, z): return x**2 + x*y**3 + z def J(x, y): return 2*x + y**3 x0, y, z = 0, 1, 4 # 先定义一个包装函数,接收所有参数但只使用需要的部分 def wrapped_jac(x, y, *unused): return J(x, y) # 用partial固定y参数,这样minimize传递的z会被*unused捕获并忽略 jac_func = partial(wrapped_jac, y=y) result = optimize.minimize(f, x0, args=(y, z), jac=jac_func) print(result)
为什么原代码会报错?
简单来说,minimize调用雅可比函数时的逻辑是:把优化变量x作为第一个参数,然后把args里的所有参数依次往后传。你的原代码中args=(y,z),所以它会尝试调用J(x, y, z),但J只定义了2个参数,自然就会抛出J() takes 2 positional arguments but 3 were given的错误。
这两种方案都不需要修改原目标函数f和雅可比函数J的定义,也不用在函数内部忽略无用参数,算是比较优雅的解决方式。
内容的提问来源于stack exchange,提问作者Marc de la Barrera i Bardalet
相关产品推荐
相关产品推荐

