Differentiation
This module implements various finite difference methods for approximating derivatives.
For multi-valued functions, it is expected that both the inputs and outputs are 1D Tensors.
Here is an example with a scalar multi-variate function:
Example:
import src/numericalnim/differentiate import arraymancer, std/math # f(x, y) = sin(x) + 2*sin(y) proc f(x: Tensor[float]): float = sin(x[0]) + 2*sin(x[1]) let x = [1.0, 1.0].toTensor let gradient = tensorGradient(f, x)Here's an example with a multi-valued function:
Example:
import src/numericalnim/differentiate import arraymancer, std/math # f(x, y) = [sin(x*y), cos(x*y)] proc f(x: Tensor[float]): Tensor[float] = result = newTensor[float](2) let arg = x[0] * x[1] result[0] = sin(arg) result[1] = cos(arg) let x = [1.0, 1.0].toTensor let jacobian = tensorJacobian(f, x)
Procs
proc checkGradient[U; T: not Tensor](f: proc (x: Tensor[U]): T; fGrad: proc (x: Tensor[U]): Tensor[T]; x0: Tensor[U]; tol: T): bool
- Checks if the provided gradient function fGrad gives the same values as numeric gradient. Source Edit
proc checkGradient[U; T](f: proc (x: Tensor[U]): Tensor[T]; fGrad: proc (x: Tensor[U]): Tensor[T]; x0: Tensor[U]; tol: T): bool
- Checks if the provided gradient function fGrad gives the same values as numeric gradient. Source Edit
proc diff1dBackward[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the derivative of f(x) at x0 using a step size h. Uses backward difference which has accuracy O(h) Source Edit
proc diff1dCentral[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the derivative of f(x) at x0 using a step size h. Uses central difference which has accuracy O(h^2) Source Edit
proc diff1dForward[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the derivative of f(x) at x0 using a step size h. Uses forward difference which has accuracy O(h) Source Edit
proc mixedDerivative[U, T](f: proc (x: Tensor[U]): T; x0: var Tensor[U]; indices: (int, int); h: U = U(0.000001)): T
- Used internally in tensorHessian. Calculates the mixed derivative dĀ²f/(dx_i dx_j). Modifies x0. Source Edit
proc secondDiff1dBackward[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the second derivative of f(x) at x0 using a step size h. Source Edit
proc secondDiff1dCentral[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the second derivative of f(x) at x0 using a step size h. Uses central difference which has accuracy O(h^2) Source Edit
proc secondDiff1dForward[U, T](f: proc (x: U): T; x0: U; h: U = U(0.000001)): T
- Numerically calculate the second derivative of f(x) at x0 using a step size h. Source Edit
proc tensorGradient[U, T](f: proc (x: Tensor[U]): Tensor[T]; x0: Tensor[U]; h: U = U(0.000001); fastMode: bool = false): Tensor[T]
-
Calculates the gradient of multi-valued f(x) w.r.t vector x at x0 using step size h. f(x) is expected to take as input and return a 1D Tensor. Every column is the gradient of one component of f. By default it uses central difference for approximating the derivatives. This requires two function evaluations per derivative. When fastMode is true it will instead use the forward difference which only uses 1 function evaluation per derivative but is less accurate.
Returns:
- The gradient as a 2D Tensor with shape (nInputs, nOutputs). This is the transpose of the Jacobian.
proc tensorGradient[U; T: not Tensor](f: proc (x: Tensor[U]): T; x0: Tensor[U]; h: U = U(0.000001); fastMode: bool = false): Tensor[ T]
-
Calculates the gradient of scalar f(x) w.r.t vector x at x0 using step size h. By default it uses central difference for approximating the derivatives. This requires two function evaluations per derivative. When fastMode is true it will instead use the forward difference which only uses 1 function evaluation per derivative but is less accurate.
Returns:
- The gradient as a 1D Tensor.
proc tensorHessian[U; T: not Tensor](f: proc (x: Tensor[U]): T; x0: Tensor[U]; h: U = U(0.000001)): Tensor[T]
-
Calculates the Hessian of a scalar function f(x) using finite differences at x0. f(x) should accept a 1D Tensor of input values.
Returns:
- The Hessian as a 2D Tensor of shape (nInputs, nInputs).
proc tensorJacobian[U, T](f: proc (x: Tensor[U]): Tensor[T]; x0: Tensor[U]; h: U = U(0.000001); fastMode: bool = false): Tensor[T]
-
Calculates the jacobian of multi-valued f(x) w.r.t vector x at x0 using step size h. f(x) is expected to take as input and return a 1D Tensor. Every row is the gradient of one component of f. By default it uses central difference for approximating the derivatives. This requires two function evaluations per derivative. When fastMode is true it will instead use the forward difference which only uses 1 function evaluation per derivative but is less accurate. Returns:
- The Jacobian as a 2D Tensor with shape (nOutputs, nInputs).