bundles / scipy 1.17.1 / scipy / differentiate / _differentiate / jacobian
function
scipy.differentiate._differentiate:jacobian
Signature
def jacobian ( f , x , * , tolerances = None , maxiter = 10 , order = 8 , initial_step = 0.5 , step_factor = 2.0 , step_direction = 0 ) Summary
Evaluate the Jacobian of a function numerically.
Parameters
f: callableThe function whose Jacobian is desired. The signature must be
f(xi: ndarray) -> ndarraywhere each element of
xiis a finite real. If the function to be differentiated accepts additional arguments, wrap it (e.g. using functools.partial orlambda) and pass the wrapped callable into jacobian.fmust not mutate the arrayxi. See Notes regarding vectorization and the dimensionality of the input and output.x: float array_likePoints at which to evaluate the Jacobian. Must have at least one dimension. See Notes regarding the dimensionality and vectorization.
tolerances: dictionary of floats, optionalAbsolute and relative tolerances. Valid keys of the dictionary are:
atol- absolute tolerance on the derivativertol- relative tolerance on the derivative
Iteration will stop when
res.error < atol + rtol * abs(res.df). The defaultatolis the smallest normal number of the appropriate dtype, and the defaultrtolis the square root of the precision of the appropriate dtype.maxiter: int, default: 10The maximum number of iterations of the algorithm to perform. See Notes.
order: int, default: 8The (positive integer) order of the finite difference formula to be used. Odd integers will be rounded up to the next even integer.
initial_step: float array_like, default: 0.5The (absolute) initial step size for the finite difference derivative approximation. Must be broadcastable with
xandstep_direction.step_factor: float, default: 2.0The factor by which the step size is reduced in each iteration; i.e. the step size in iteration 1 is
initial_step/step_factor. Ifstep_factor < 1, subsequent steps will be greater than the initial step; this may be useful if steps smaller than some threshold are undesirable (e.g. due to subtractive cancellation error).step_direction: integer array_likeAn array representing the direction of the finite difference steps (e.g. for use when
xlies near to the boundary of the domain of the function.) Must be broadcastable withxandinitial_step. Where 0 (default), central differences are used; where negative (e.g. -1), steps are non-positive; and where positive (e.g. 1), all steps are non-negative.
Returns
res: _RichResultAn object similar to an instance of scipy.optimize.OptimizeResult with the following attributes. The descriptions are written as though the values will be scalars; however, if
freturns an array, the outputs will be arrays of the same shape.success
success
status
status
df
df
error
error
nit
nit
nfev
nfev
Each element of an attribute is associated with the corresponding element of
df. For instance, elementiofnfevis the number of points at whichfwas evaluated for the sake of computing elementiofdf.
Notes
Suppose we wish to evaluate the Jacobian of a function . Assign to variables m and n the positive integer values of and , respectively, and let ... represent an arbitrary tuple of integers. If we wish to evaluate the Jacobian at a single point, then:
argument
xmust be an array of shape(m,)argument
fmust be vectorized to accept an array of shape(m, ...). The first axis represents the inputs of ; the remainder are for evaluating the function at multiple points in a single call.argument
fmust return an array of shape(n, ...). The first axis represents the outputs of ; the remainder are for the result of evaluating the function at multiple points.attribute
dfof the result object will be an array of shape(n, m), the Jacobian.
This function is also vectorized in the sense that the Jacobian can be evaluated at k points in a single call. In this case, x would be an array of shape (m, k), f would accept an array of shape (m, k, ...) and return an array of shape (n, k, ...), and the df attribute of the result would have shape (n, m, k).
Suppose the desired callable f_not_vectorized is not vectorized; it can only accept an array of shape (m,). A simple solution to satisfy the required interface is to wrap f_not_vectorized as follows
def f(x): return np.apply_along_axis(f_not_vectorized, axis=0, arr=x)
Alternatively, suppose the desired callable f_vec_q is vectorized, but only for 2-D arrays of shape (m, q). To satisfy the required interface, consider
def f(x): m, batch = x.shape[0], x.shape[1:] # x.shape is (m, ...) x = np.reshape(x, (m, -1)) # `-1` is short for q = prod(batch) res = f_vec_q(x) # pass shape (m, q) to function n = res.shape[0] return np.reshape(res, (n,) + batch) # return shape (n, ...)
Then pass the wrapped callable f as the first argument of jacobian.
Array API Standard Support
jacobian has experimental support for Python Array API Standard compatible backends in addition to NumPy. Please consider testing these features by setting an environment variable SCIPY_ARRAY_API=1 and providing CuPy, PyTorch, JAX, or Dask arrays as array arguments. The following combinations of backend and device (or other capability) are supported.
==================== ==================== ==================== Library CPU GPU ==================== ==================== ==================== NumPy ✅ n/a CuPy n/a ✅ PyTorch ✅ ✅ JAX ⚠️ no JIT ⚠️ no JIT Dask ⛔ n/a ==================== ==================== ====================
See
dev-arrayapifor more information.
Examples
The Rosenbrock function maps from :math:`\mathbf{R}^m \rightarrow \mathbf{R}`; the SciPy implementation `scipy.optimize.rosen` is vectorized to accept an array of shape ``(m, p)`` and return an array of shape ``p``. Suppose we wish to evaluate the Jacobian (AKA the gradient because the function returns a scalar) at ``[0.5, 0.5, 0.5]``.import numpy as np from scipy.differentiate import jacobian from scipy.optimize import rosen, rosen_der m = 3 x = np.full(m, 0.5) res = jacobian(rosen, x) ref = rosen_der(x) # reference value of the gradient res.df, ref✓
def f(x): x1, x2, x3 = x return [x1, 5*x3, 4*x2**2 - 2*x3, x3*np.sin(x1)]✓
def df(x): x1, x2, x3 = x one = np.ones_like(x1) return [[one, 0*one, 0*one], [0*one, 0*one, 5*one], [0*one, 8*x2, -2*one], [x3*np.cos(x1), 0*one, np.sin(x1)]]✓
rng = np.random.default_rng(389252938452) x = rng.random(size=3) res = jacobian(f, x) ref = df(x) res.df.shape == (4, 3) np.allclose(res.df, ref)✓
x = rng.random(size=(3, 10)) res = jacobian(f, x) ref = df(x) res.df.shape == (4, 3, 10) np.allclose(res.df, ref)✓
See also
- derivative
- hessian
Aliases
-
scipy.differentiate.jacobian