如何让 scipyfmin_cg
使用一个返回cost
并gradient
作为元组的函数?具有f
成本和fprime
梯度的问题是,我可能必须执行两次计算grad
and的操作(非常昂贵) cost
。此外,在它们之间共享变量可能很麻烦。
然而,在 Matlab 中,fmin_cg
使用一个将成本和梯度作为元组返回的函数。我不明白为什么 scipyfmin_cg
不能提供这样的便利。
提前致谢...
如何让 scipyfmin_cg
使用一个返回cost
并gradient
作为元组的函数?具有f
成本和fprime
梯度的问题是,我可能必须执行两次计算grad
and的操作(非常昂贵) cost
。此外,在它们之间共享变量可能很麻烦。
然而,在 Matlab 中,fmin_cg
使用一个将成本和梯度作为元组返回的函数。我不明白为什么 scipyfmin_cg
不能提供这样的便利。
提前致谢...
您可以scipy.optimize.minimize
使用jac=True
. 如果由于某种原因这不是一个选项,那么您可以查看它如何处理这种情况:
class MemoizeJac(object):
""" Decorator that caches the value gradient of function each time it
is called. """
def __init__(self, fun):
self.fun = fun
self.jac = None
self.x = None
def __call__(self, x, *args):
self.x = numpy.asarray(x).copy()
fg = self.fun(x, *args)
self.jac = fg[1]
return fg[0]
def derivative(self, x, *args):
if self.jac is not None and numpy.alltrue(x == self.x):
return self.jac
else:
self(x, *args)
return self.jac
这个类包装了一个返回函数值和梯度的函数,保持一个元素缓存并检查它是否已经知道它的结果。用法:
fmemo = MemoizeJac(f, fprime)
xopt = fmin_cg(fmemo, x0, fmemo.derivative)
这段代码的奇怪之处在于它假设f
总是在之前被调用fprime
(但不是每个f
调用都跟着一个fprime
调用)。我不确定是否scipy.optimize
真的能保证这一点,但代码可以很容易地调整为不做出这种假设。上述的强大版本(未经测试):
class MemoizeJac(object):
def __init__(self, fun):
self.fun = fun
self.value, self.jac = None, None
self.x = None
def _compute(self, x, *args):
self.x = numpy.asarray(x).copy()
self.value, self.jac = self.fun(x, *args)
def __call__(self, x, *args):
if self.value is not None and numpy.alltrue(x == self.x):
return self.value
else:
self._compute(x, *args)
return self.value
def derivative(self, x, *args):
if self.jac is not None and numpy.alltrue(x == self.x):
return self.jac
else:
self._compute(x, *args)
return self.jac