如何在一个函数中计算 objective、梯度和 hessian 并将其传递给 scipy.optimize.minimize?
How to compute objective, gradient and hessian within one function and pass it to scipy.optimize.minimize?
根据 docs,如果 jac
是布尔值且 True
,则 objective
函数 fun
被假定为 return (f, grad)
,即 objective 值
和梯度。这有助于避免重复计算
objective 和梯度中出现的术语。
现在我想知道是否有类似的选择或方法来实现
对于 hessian hess
也是如此,这样 objective 函数可以 return
元组 (f, grad, hess)
,其中 hess
是 hessian 矩阵?
这是一个 MWE:
import numpy as np
from scipy.optimize import minimize
def obj_and_grad_and_hess(x):
obj = np.exp(x) * x**2
grad = obj + 2*np.exp(x)*x
hess = obj + 4*np.exp(x)*(x) + 2*np.exp(x)
return obj, grad, hess
# res = minimize(obj_and_grad_and_hess, x0=[1.0], jac=True, hess=True)
这个问题是
类似于 ,其中
jacobian 函数可以 return jacobian 和 hessian。
在后台,scipy.optimize.minimize 使用 MemoizeJac
处理 jac=True
案例的装饰器。装饰器在每次调用时都会缓存函数的 return 值 f
和 grad
。通过从这个 class 继承,你可以用同样的方式实现一个 MemoizeJacHess
装饰器:
from scipy.optimize.optimize import MemoizeJac
class MemoizeJacHess(MemoizeJac):
""" Decorator that caches the return vales of a function returning
(fun, grad, hess) each time it is called. """
def __init__(self, fun):
super().__init__(fun)
self.hess = None
def _compute_if_needed(self, x, *args):
if not np.all(x == self.x) or self._value is None or self.jac is None or self.hess is None:
self.x = np.asarray(x).copy()
self._value, self.jac, self.hess = self.fun(x, *args)
def hessian(self, x, *args):
self._compute_if_needed(x, *args)
return self.hess
但是,由于尚不支持 hess=True
选项,您必须
像这样使用它:
obj = MemoizeJacHess(obj_and_grad_and_hess)
grad = obj.derivative
hess = obj.hessian
res = minimize(obj, x0=[1.0], jac=grad, hess=hess)
根据 docs,如果 jac
是布尔值且 True
,则 objective
函数 fun
被假定为 return (f, grad)
,即 objective 值
和梯度。这有助于避免重复计算
objective 和梯度中出现的术语。
现在我想知道是否有类似的选择或方法来实现
对于 hessian hess
也是如此,这样 objective 函数可以 return
元组 (f, grad, hess)
,其中 hess
是 hessian 矩阵?
这是一个 MWE:
import numpy as np
from scipy.optimize import minimize
def obj_and_grad_and_hess(x):
obj = np.exp(x) * x**2
grad = obj + 2*np.exp(x)*x
hess = obj + 4*np.exp(x)*(x) + 2*np.exp(x)
return obj, grad, hess
# res = minimize(obj_and_grad_and_hess, x0=[1.0], jac=True, hess=True)
这个问题是
类似于
在后台,scipy.optimize.minimize 使用 MemoizeJac
处理 jac=True
案例的装饰器。装饰器在每次调用时都会缓存函数的 return 值 f
和 grad
。通过从这个 class 继承,你可以用同样的方式实现一个 MemoizeJacHess
装饰器:
from scipy.optimize.optimize import MemoizeJac
class MemoizeJacHess(MemoizeJac):
""" Decorator that caches the return vales of a function returning
(fun, grad, hess) each time it is called. """
def __init__(self, fun):
super().__init__(fun)
self.hess = None
def _compute_if_needed(self, x, *args):
if not np.all(x == self.x) or self._value is None or self.jac is None or self.hess is None:
self.x = np.asarray(x).copy()
self._value, self.jac, self.hess = self.fun(x, *args)
def hessian(self, x, *args):
self._compute_if_needed(x, *args)
return self.hess
但是,由于尚不支持 hess=True
选项,您必须
像这样使用它:
obj = MemoizeJacHess(obj_and_grad_and_hess)
grad = obj.derivative
hess = obj.hessian
res = minimize(obj, x0=[1.0], jac=grad, hess=hess)