在scipy中优化一个不显式定义梯度的函数
我现在正在尝试用scipy来优化一个函数。我对变量有一些限制,从这个链接看:http://docs.scipy.org/doc/scipy-0.14.0/reference/tutorial/optimize.html,SLSQP正好符合我的需求。在他们的例子中,他们有一个明确的公式来表示输入和结果之间的关系,从中可以找到梯度。但是我有一个非常复杂且计算量巨大的函数,它计算电磁场如何在金属墙上反弹,这个函数无法用简单的公式表达(如果你感兴趣,我在使用MEEP FDTD Python模拟)。请问scipy中有没有类似的函数,可以帮我找到一个函数的梯度,然后进行优化?或者说,scipy中有没有其他函数(任何基本的Python库也可以)可以帮我找到一个函数的梯度,我再把这个梯度传入优化程序?任何建议都非常感谢。
2 个回答
看起来 scipy.optimize.minimize
的 SLSQP 方法并不一定需要梯度。可以看看这个开源项目,arch,在大约 738-748 行的代码中,他们使用了 SLSQP,但并没有提供梯度。就像这样:
opt = minimize(
func,
sv,
args=args,
method="SLSQP",
bounds=bounds,
constraints=ineq_constraints,
tol=tol,
callback=_callback,
options=options,
)
另外,在版本 1.8.0
中,下面的代码片段也能正常工作:
import scipy.optimize
res = scipy.optimize.minimize(
lambda x: x[0]**2, [3.],
method='SLSQP', bounds=[(1., None)])
print(res.success) #: True
这也证明了这一点。
我没有深入研究 scipy 的代码,但我猜如果你不提供解析梯度,它会计算数值梯度。
因为你可能很难轻松计算梯度,所以使用一种不需要梯度的优化算法可能会更有效。下面是一些在SciPy中可用的算法概述:
http://scipy-lectures.github.io/advanced/mathematical_optimization/#gradient-less-methods
还有一种叫做“盆地跳跃”的算法,它和模拟退火有点相似,但在上面的页面没有提到:
http://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.basinhopping.html