scipy 用既返回值又返回雅可比行列式的函数求解非线性最小二乘问题

cfh9epnr  于 2022-11-10  发布在  其他
关注(0)|答案(3)|浏览(145)

我正在尝试用Python加速求解一个非线性最小二乘问题。我可以通过一个正向通道(val, jac) = fun计算函数值和雅可比行列式。像scipy.optimize.least_squares这样的求解器只接受两个单独的函数funjac,这对于我的问题来说意味着每次迭代必须计算两次函数值(一次在fun中,一次在jac中)。
有没有一个技巧,可以避免两次解决原始问题?
更通用的函数scipy.optimize.minimize支持上面的风格,带有jac=True关键字,但是对于我的问题来说,它很慢。

8yparm6h

8yparm6h1#

我认为最好的方法是使用MemoizeJac装饰器。这正是scipy.optimize.minimizejac=True的引擎盖下所做的:

import numpy as np
from scipy.optimize import least_squares
from scipy.optimize._optimize import MemoizeJac

def fun_and_jac(x):
    return x**2 - 5 * x + 3, 2 * x - 5

fun = MemoizeJac(fun_and_jac)
jac = fun.derivative

res = least_squares(fun, x0=0, jac=jac)
print(res)
sycxhyv7

sycxhyv72#

你可以做一点黑客:

val_cache = {}
jac_cache = {}

def val_fun(*args):
    try:
        return val_cache.pop(args)
    except KeyError:
        (val, jac) = fun(*args)
        jac_cache[args] = jac
        return val

def jac_fun(*args):
    try:
        return jac_cache.pop(args)
    except KeyError:
        (val, jac) = fun(*args)
        val_cache[args] = val
        return jac
mm5n2pyu

mm5n2pyu3#

scipy.optimize.minimize的文档中:
如果jac是布尔值且为True,则假定fun返回包含目标函数和梯度的元组(f,g)。
https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.minimize.html?highlight=minimize
因此,您可以简单地这样做:

from scipy.optimize import minimize

def function(x):
    '''Function that returns both fun and jac'''
    return x**2 - 5 * x + 3, 2 * x - 5

print(minimize(function, 0, jac=True))

编辑,重新阅读您的问题,似乎此选项也适用于least_squares,但未记录。
这也是可行的:

from scipy.optimize import least_squares

def function(x):
    '''Function that returns both fun and jac'''
    return x**2 - 5 * x + 3, 2 * x - 5

print(least_squares(function, 0, jac=True))

相关问题