简体   繁体   English

高阶多元导数

[英]Higher-order multivariate derivatives

Is there a packaged way to compute higher-order multivariate derivatives (using finite differences, not symbolic calculations) in Python? 在Python中是否有一种打包的方法来计算高阶多元导数(使用有限差分,而不是符号计算)?

For example, if f computes the function cos(x)*y from R^2 to R, ie, f takes numpy arrays of shape 2 and returns floats (or arrays of shape () ), is there a function partial such that partial([2,1])(f) computes the function (d^2/dx^2)(d/dy)f = -cos(x)*1 from R^2 to R, eg 例如,如果f计算从R ^ 2到R的函数cos(x)* y,即f接受形状2 numpy数组并返回浮点数(或shape ()数组),那么是否存在partial函数,使得partial([2,1])(f)计算函数(d ^ 2 / dx ^ 2)(d / dy)f = -cos(x)* 1从R ^ 2到R,例如

np.isclose(partial([2,1])(f)(0),1.0)

There is a host of finite difference tools in the default libraries (so much for ''one way to do it''): 默认库中有许多有限差分工具(“一种方法”太多了):

https://docs.scipy.org/doc/scipy/reference/generated/scipy.misc.derivative.html https://docs.scipy.org/doc/numpy/reference/generated/numpy.gradient.html https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.optimize.approx_fprime.html https://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.misc.central_diff_weights.html https://github.com/statsmodels/statsmodels/blob/master/statsmodels/tools/numdiff.py https://docs.scipy.org/doc/scipy/reference/generation/scipy.misc.derivative.html https://docs.scipy.org/doc/numpy/reference/generation/numpy.gradient.html https: //docs.scipy.org/doc/scipy-0.14.0/reference/generation/scipy.optimize.approx_fprime.html https://docs.scipy.org/doc/scipy-0.14.0/reference/generation/scipy .misc.central_diff_weights.html https://github.com/statsmodels/statsmodels/blob/master/statsmodels/tools/numdiff.py

However, none of them can handle both multivariate functions and higher-order derivatives, ie, none of them can handle the job above. 但是,它们都不能处理多元函数和高阶导数,即它们都不能处理上面的工作。

(There is also https://pypi.org/project/numdifftools/ but it seems to fall just short of doing what I need. The authors haven't responded to my question.) (也有https://pypi.org/project/numdifftools/,但这似乎不足以满足我的要求。作者们没有回答我的问题。)

It's easy to write the tool myself. 自己编写工具很容易。 However, it seems to be surprisingly difficult to do so well, ie, in an accurate and stable fashion. 然而,似乎很难做到这一点,即以准确和稳定的方式。 For example, a straightforward recursive implementation is unstable for mesh-widths smaller than 1e-3 , even for simple functions like the one above and for mixed derivatives of only second order. 例如,对于小于1e-3网格宽度,即使对于上述简单函数以及仅是二阶混合导数,直接的递归实现也是不稳定的。

PS: I am not asking for finite differences of an array ( https://docs.scipy.org/doc/numpy/reference/generated/numpy.diff.html and https://github.com/maroba/findiff do that). PS:我不是在要求数组的有限差异( https://docs.scipy.org/doc/numpy/reference/generated/numpy.diff.htmlhttps://github.com/maroba/findiff会做到这一点)。 I need to evaluate derivatives at arbitrary points without computing the values of the function on a full cartesian grid. 我需要在任意点上评估导数,而无需在完整的笛卡尔网格上计算函数的值。

There's scipy.optimize._approx_derivative which does it. scipy.optimize._approx_derivative可以做到。 This is however not a public function, so if you end up using it, you're on your own. 但是,这不是公共功能,因此,如果最终使用它,您将自己承担责任。

You can write a wrapper and use the scipy.misc.derivative function. 您可以编写包装器并使用scipy.misc.derivative函数。

For a simple x, y derivative, use this answer 对于简单的x,y导数,请使用答案

For a vector derivative, you can define g(t, (x, y), vector) = f((x,y) + t * vector) , which yields g'(0, args=((x,y), vector)) = directional derivative in the chosen vector direction 对于向量导数,您可以定义g(t, (x, y), vector) = f((x,y) + t * vector) ,得出g'(0, args=((x,y), vector)) =所选向量方向上的方向导数

from scipy.misc import derivative

f = lambda x: x[0] * np.cos(x[1])

def vector_derivative(f, x0, vector, delta=1):
    def wrapper(x, x0, vector):
        return f(np.asarray(x0) + x * np.asarray(vector))
    return derivative(wrapper, 0, args=(x0, vector), dx=delta)

vector_derivative(f, [1, np.pi/2], [0, 1], delta=0.01)
>> -0.9999833334166673

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM