bundles / scipy 1.17.1 / scipy / optimize / _numdiff / approx_derivative
function
scipy.optimize._numdiff:approx_derivative
source: /scipy/optimize/_numdiff.py :278
Signature
def approx_derivative ( fun , x0 , method = 3-point , rel_step = None , abs_step = None , f0 = None , bounds = (-inf, inf) , sparsity = None , as_linear_operator = False , args = () , kwargs = None , full_output = False , workers = None ) Summary
Compute finite difference approximation of the derivatives of a vector-valued function.
Extended Summary
If a function maps from R^n to R^m, its derivatives form m-by-n matrix called the Jacobian, where an element (i, j) is a partial derivative of f[i] with respect to x[j].
Parameters
fun: callableFunction of which to estimate the derivatives. The argument x passed to this function is ndarray of shape (n,) (never a scalar even if n=1). It must return 1-D array_like of shape (m,) or a scalar.
x0: array_like of shape (n,) or floatPoint at which to estimate the derivatives. Float will be converted to a 1-D array.
method: {'3-point', '2-point', 'cs'}, optionalFinite difference method to use:
'2-point' - use the first order accuracy forward or backward
difference.
'3-point' - use central difference in interior points and the
second order accuracy forward or backward difference near the boundary.
'cs' - use a complex-step finite difference scheme. This assumes
that the user function is real-valued and can be analytically continued to the complex plane. Otherwise, produces bogus results.
rel_step: None or array_like, optionalRelative step size to use. If None (default) the absolute step size is computed as
h = rel_step * sign(x0) * max(1, abs(x0)), withrel_stepbeing selected automatically, see Notes. Otherwiseh = rel_step * sign(x0) * abs(x0). Formethod='3-point'the sign ofhis ignored. The calculated step size is possibly adjusted to fit into the bounds.abs_step: array_like, optionalAbsolute step size to use, possibly adjusted to fit into the bounds. For
method='3-point'the sign ofabs_stepis ignored. By default relative steps are used, only ifabs_step is not Noneare absolute steps used.f0: None or array_like, optionalIf not None it is assumed to be equal to
fun(x0), in this case thefun(x0)is not called. Default is None.bounds: tuple of array_like, optionalLower and upper bounds on independent variables. Defaults to no bounds. Each bound must match the size of
x0or be a scalar, in the latter case the bound will be the same for all variables. Use it to limit the range of function evaluation. Bounds checking is not implemented whenas_linear_operatoris True.sparsity: {None, array_like, sparse array, 2-tuple}, optionalDefines a sparsity structure of the Jacobian matrix. If the Jacobian matrix is known to have only few non-zero elements in each row, then it's possible to estimate its several columns by a single function evaluation [3]. To perform such economic computations two ingredients are required:
structurearray_like or sparse array of shape (m, n). A zero element means that a corresponding element of the Jacobian identically equals to zero.
groupsarray_like of shape (n,). A column grouping for a given sparsity structure, use group_columns to obtain it.
A single array or a sparse array is interpreted as a sparsity structure, and groups are computed inside the function. A tuple is interpreted as (structure, groups). If None (default), a standard dense differencing will be used.
Note, that sparse differencing makes sense only for large Jacobian matrices where each row contains few non-zero elements.
as_linear_operator: bool, optionalWhen True the function returns an scipy.sparse.linalg.LinearOperator. Otherwise it returns a dense array or a sparse array depending on
sparsity. The linear operator provides an efficient way of computingJ.dot(p)for any vectorpof shape (n,), but does not allow direct access to individual elements of the matrix. By defaultas_linear_operatoris False.args, kwargs: tuple and dict, optionalAdditional arguments passed to
fun. Both empty by default. The calling signature isfun(x, *args, **kwargs).full_output: bool, optionalIf True then the function also returns a dictionary with extra information about the calculation.
workers: int or map-like callable, optionalSupply a map-like callable, such as
multiprocessing.Pool.mapfor evaluating the population in parallel. This evaluation is carried out asworkers(fun, iterable). Alternatively, ifworkersis an int the task is subdivided intoworkerssections and the fun evaluated in parallel (usesmultiprocessing.Pool <multiprocessing>). Supply -1 to use all available CPU cores. It is recommended that a map-like be used instead of int, as repeated calls to approx_derivative will incur large overhead from setting up new processes.
Returns
J: {ndarray, sparse array, LinearOperator}Finite difference approximation of the Jacobian matrix. If
as_linear_operatoris True returns a LinearOperator with shape (m, n). Otherwise it returns a dense array or sparse array depending on howsparsityis defined. Ifsparsityis None then a ndarray with shape (m, n) is returned. Ifsparsityis not None returns a csr_array or csr_matrix with shape (m, n) following the array/matrix type of the incoming structure. For sparse arrays and linear operators it is always returned as a 2-D structure. For ndarrays, if m=1 it is returned as a 1-D gradient array with shape (n,).info_dict: dictDictionary containing extra information about the calculation. The keys include:
nfev, number of function evaluations. Ifas_linear_operatoris Truethen
funis expected to track the number of evaluations itself. This is because multiple calls may be made to the linear operator which are not trackable here.
Notes
If rel_step is not provided, it assigned as EPS**(1/s), where EPS is determined from the smallest floating point dtype of x0 or fun(x0), np.finfo(x0.dtype).eps, s=2 for '2-point' method and s=3 for '3-point' method. Such relative step approximately minimizes a sum of truncation and round-off errors, see [1]. Relative steps are used by default. However, absolute steps are used when abs_step is not None. If any of the absolute or relative steps produces an indistinguishable difference from the original x0, (x0 + dx) - x0 == 0, then a automatic step size is substituted for that particular entry.
A finite difference scheme for '3-point' method is selected automatically. The well-known central difference scheme is used for points sufficiently far from the boundary, and 3-point forward or backward scheme is used for points near the boundary. Both schemes have the second-order accuracy in terms of Taylor expansion. Refer to [2] for the formulas of 3-point forward and backward difference schemes.
For dense differencing when m=1 Jacobian is returned with a shape (n,), on the other hand when n=1 Jacobian is returned with a shape (m, 1). Our motivation is the following: a) It handles a case of gradient computation (m=1) in a conventional way. b) It clearly separates these two different cases. b) In all cases np.atleast_2d can be called to get 2-D Jacobian with correct dimensions.
Examples
import numpy as np from scipy.optimize._numdiff import approx_derivative def f(x, c1, c2): return np.array([x[0] * np.sin(c1 * x[1]), x[0] * np.cos(c2 * x[1])]) x0 = np.array([1.0, 0.5 * np.pi]) approx_derivative(f, x0, args=(1, 2))✓
def g(x): return x**2 if x >= 1 else x x0 = 1.0✓
approx_derivative(g, x0, bounds=(-np.inf, 1.0)) approx_derivative(g, x0, bounds=(1.0, np.inf))✗
from multiprocessing import Pool import time def fun2(x): # import from an external file for use with multiprocessing time.sleep(0.002) return rosen(x)✓
rng = np.random.default_rng() x0 = rng.uniform(high=10, size=(2000,))✓
f0 = rosen(x0)
⚠%timeit approx_derivative(fun2, x0, f0=f0) # may vary
⚠elapsed = []
✓with Pool() as workers: for i in range(10): t = time.perf_counter() approx_derivative(fun2, x0, workers=workers.map, f0=f0) et = time.perf_counter() elapsed.append(et - t)⚠
np.mean(elapsed) # may vary
✗def fun(f, x, *args, **kwds): xx = np.r_[[xs for xs in x]] return f(xx.T)✓
%timeit approx_derivative(fun2, x0, workers=fun, f0=f0) # may vary
⚠See also
- check_derivative
Check correctness of a function computing derivatives.
Aliases
-
scipy.optimize._differentiable_functions.approx_derivative