如何在一个函数中计算目标、梯度和hessian,并将其传递给scipy.optimize.minimize?

2024-05-15 12:39:11 发布

您现在位置:Python中文网/ 问答频道 /正文

根据docs,如果jac是一个布尔和True,那么目标 假定函数fun返回(f, grad),即目标值 还有梯度。这有助于避免重复计算 目标和梯度中出现的术语

现在我想知道是否有类似的选择或方法来实现 对于hessian hess也一样,这样目标函数可以返回 元组(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)

这个问题是 类似于this question,其中 雅可比函数可以返回雅可比矩阵和海森矩阵


Tags: and函数importtrueobjdocs目标np
1条回答
网友
1楼 · 发布于 2024-05-15 12:39:11

在引擎盖下,scipy.optimize.minimize使用^{} 修饰程序来处理jac=True情况。每次调用函数时,decorator都会缓存函数的返回值fgrad。通过从此类继承,您可以以同样的方式实现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)

相关问题 更多 >