首页 > 解决方案 > 如何在一个函数中计算目标、梯度和粗麻布并将其传递给 scipy.optimize.minimize?

问题描述

根据docs,如果jac是一个布尔值 和True,则假定目标函数fun返回(f, grad),即目标值和梯度。这对于避免在目标和梯度中出现的项的重复计算很有用。

现在我想知道是否有类似的选项或方法可以为 hessian 实现相同的hess目标函数可以返回一个元组(f, grad, hess)hesshessian 矩阵在哪里?

这是一个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 函数可以返回 jacobian 和 hessian。

标签: pythonscipyscipy-optimizescipy-optimize-minimize

解决方案


在引擎盖下, scipy.optimize.minimize 使用MemoizeJac 装饰器来处理jac=True案例。装饰器缓存函数的返回值f以及grad每次调用它。通过从此类继承,您可以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)

推荐阅读