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.
我正在阅读jacobian Matrix,尝试构建一个,从我到目前为止所读到的,这个python代码应该被视为jacobian。我明白了吗?
答案 0 :(得分:4)
Jacobian仅针对向量值函数进行定义。你不能使用填充常量的数组来计算雅可比矩阵;你必须知道基础函数及其偏导数,或者这些函数的数值近似。当您考虑常量(相对于某事物)的(部分)导数为0时,这是显而易见的。
在Python中,您可以使用符号数学模块,例如SymPy
或SymEngine
来计算函数的雅可比行列式。这是维基百科示例的简单演示:
使用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
答案 1 :(得分:4)
您可以使用哈佛autograd
库(link),其中grad
和jacobian
以函数作为参数:
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]))
否则,您可以使用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)
此外,您可能还希望看到此低级变体(link)。
答案 2 :(得分:2)
在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'])
给出:
Matrix([[2, 3],[2, -3]])
答案 3 :(得分:2)
尽管autograd
是一个很好的库,但请务必检查其upgraded version JAX,该文件已被很好地记录下来(与autograd相比)。
一个简单的例子:
import jax.numpy as jnp
from jax import jacfwd
# Define some simple function.
def sigmoid(x):
return 0.5 * (jnp.tanh(x / 2) + 1)
# Note that here, I want a derivative of a "vector" output function (inputs*a + b is a vector) wrt a input
# "vector" a at a0: Derivative of vector wrt another vector is a matrix: The Jacobian
def simpleJ(a, b, inputs): #inputs is a matrix, a & b are vectors
return sigmoid(jnp.dot(inputs, a) + b)
inputs = jnp.array([[0.52, 1.12, 0.77],
[0.88, -1.08, 0.15],
[0.52, 0.06, -1.30],
[0.74, -2.49, 1.39]])
b = jnp.array([0.2, 0.1, 0.3, 0.2])
a0 = jnp.array([0.1,0.7,0.7])
# Isolate the function: variables to be differentiated from the constant parameters
f = lambda a: simpleJ(a, b, inputs) # Now f is just a function of variable to be differentiated
J = jacfwd(f)
# Till now I have only calculated the derivative, it still needs to be evaluated at a0.
J(a0)
答案 4 :(得分:1)
这是向量函数f(x)
的数学Jacobian的python实现,假定该函数返回一维numpy数组。
import numpy as np
def J(f,x,dx):
n=len(x)
func=f(x)
jac=np.zeros((n,n))
for j in range(n): #through columns
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
建议制作dx〜10 ^ -8。
答案 5 :(得分:0)
如果您想一次通过数值找到许多点的雅可比行列式(例如,如果您的函数接受形状(n,x)并输出(n,y)),则为一个函数。从本质上讲,这是詹姆斯·卡特的答案,但有很多要点。 dx可能需要根据他的答案中的绝对值进行调整。
def numerical_jacobian(f, xs, dx=1e-6):
"""
f is a function that accepts input of shape (n_points, input_dim)
and outputs (n_points, output_dim)
return the jacobian as (n_points, output_dim, input_dim)
"""
if len(xs.shape) == 1:
xs = xs[np.newaxis, :]
assert len(xs.shape) == 2
ys = f(xs)
x_dim = xs.shape[1]
y_dim = ys.shape[1]
jac = np.empty((xs.shape[0], y_dim, x_dim))
for i in range(x_dim):
x_try = xs + dx * e(x_dim, i + 1)
jac[:, :, i] = (f(x_try) - ys) / dx
return jac
def e(n, i):
ret = np.zeros(n)
ret[i - 1] = 1.0
return ret