在 Python 中计算雅可比矩阵

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49553006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 19:07:37  来源:igfitidea点击:

Compute the Jacobian matrix in Python

pythonnumpyderivative

提问by filtertips

import numpy as np


a = np.array([[1,2,3],
              [4,5,6],
              [7,8,9]])


b = np.array([[1,2,3]]).T

c = a.dot(b) #function

jacobian = a # as partial derivative of c w.r.t to b is a.

I am reading about jacobian Matrix, trying to build one and from what I have read so far, this python code should be considered as jacobian. Am I understanding this right?

我正在阅读有关 jacobian Matrix 的文章,试图构建一个,根据我目前所读到的内容,这个 python 代码应该被视为 jacobian。我理解正确吗?

回答by Adam Erickson

You can use the Harvard autogradlibrary (link), where gradand jacobiantake a function as their argument:

您可以使用哈佛autograd库 ( link),其中gradjacobian以函数作为参数:

import autograd.numpy as np
from autograd import grad, jacobian

x = np.array([5,3], dtype=float)

def cost(x):
    return x[0]**2 / x[1] - np.log(x[1])

gradient_cost = grad(cost)
jacobian_cost = jacobian(cost)

gradient_cost(x)
jacobian_cost(np.array([x,x,x]))

Otherwise, you could use the jacobianmethod available for matrices in sympy:

否则,您可以使用jacobian可用于矩阵的方法sympy

from sympy import sin, cos, Matrix
from sympy.abc import rho, phi

X = Matrix([rho*cos(phi), rho*sin(phi), rho**2])
Y = Matrix([rho, phi])

X.jacobian(Y)

Also, you may also be interested to see this low-level variant (link). MATLAB provides nice documentation on its jacobianfunction here.

此外,您可能也有兴趣查看此低级变体(链接)。MATLAB 在这里提供了关于其jacobian功能的很好的文档。

回答by dROOOze

The Jacobian is only defined for vector-valued functions. You cannot work with arrays filled with constants to calculate the Jacobian; you must know the underlying function and its partial derivatives, or the numerical approximation of these. This is obvious when you consider that the (partial) derivative of a constant (with respect to something) is 0.

雅可比行列式仅针对向量值函数定义。您不能使用填充常量的数组来计算雅可比行列式;您必须知道基础函数及其偏导数,或它们的数值近似。当您考虑常数(关于某物)的(偏)导数为 0 时,这一点很明显。

In Python, you can work with symbolic math modules such as SymPyor SymEngineto calculate Jacobians of functions. Here's a simple demonstration of an example from Wikipedia:

在 Python 中,您可以使用符号数学模块,例如SymPySymEngine来计算函数的雅可比矩阵。以下是维基百科示例的简单演示:

enter image description here

在此处输入图片说明

Using the SymEnginemodule:

使用SymEngine模块:

Python 2.7.11 (v2.7.11:6d1b6a68f775, Dec  5 2015, 20:40:30) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>
>>> import symengine
>>>
>>>
>>> vars = symengine.symbols('x y') # Define x and y variables
>>> f = symengine.sympify(['y*x**2', '5*x + sin(y)']) # Define function
>>> J = symengine.zeros(len(f),len(vars)) # Initialise Jacobian matrix
>>>
>>> # Fill Jacobian matrix with entries
... for i, fi in enumerate(f):
...     for j, s in enumerate(vars):
...         J[i,j] = symengine.diff(fi, s)
...
>>> print J
[2*x*y, x**2]
[5, cos(y)]
>>>
>>> print symengine.Matrix.det(J)
2*x*y*cos(y) - 5*x**2

回答by OliverQ

In python 3, you can try sympy package:

在python 3中,你可以试试sympy包:

import sympy as sym

def Jacobian(v_str, f_list):
    vars = sym.symbols(v_str)
    f = sym.sympify(f_list)
    J = sym.zeros(len(f),len(vars))
    for i, fi in enumerate(f):
        for j, s in enumerate(vars):
            J[i,j] = sym.diff(fi, s)
    return J

Jacobian('u1 u2', ['2*u1 + 3*u2','2*u1 - 3*u2'])

which gives out:

它给出:

Matrix([[2,  3],[2, -3]])

回答by James Carter

Here is a Python implementation of the mathematical Jacobian of a vector function f(x), which is assumed to return a 1-D numpy array.

这是向量函数的数学雅可比行列式的 Python 实现,f(x)假设它返回一维 numpy 数组。

import numpy as np

def J(f, x, dx=1e-8):
    n = len(x)
    func = f(x)
    jac = np.zeros((n, n))
    for j in range(n):  # through columns to allow for vector addition
        Dxj = (abs(x[j])*dx if x[j] != 0 else dx)
        x_plus = [(xi if k != j else xi + Dxj) for k, xi in enumerate(x)]
        jac[:, j] = (f(x_plus) - func)/Dxj
    return jac

It is recommended to make dx~ 10-8.

建议制作dx~ 10 -8