微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何在一个函数内计算目标、梯度和粗麻布并将其传递给 scipy.optimize.minimize?

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

根据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,hess

# res = minimize(obj_and_grad_and_hess,x0=[1.0],jac=True,hess=True)

这个问题是 类似于 this question,其中 jacobian 函数可以返回 jacobian 和 hessian。

解决方法

在幕后,scipy.optimize.minimize 使用 MemoizeJac 处理 jac=True 情况的装饰器。装饰器每次调用时都会缓存函数的返回值 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,*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)

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。