Model#

class cuqi.model.Model(forward, range_geometry, domain_geometry, gradient=None, jacobian=None)#

Generic model defined by a forward operator.

Parameters:
  • forward (callable function) – Forward operator of the model. It takes one or more inputs and returns the model output.

  • range_geometry (integer, a 1D or 2D tuple of integers, cuqi.geometry.Geometry) – If integer or 1D tuple of integers is given, a cuqi.geometry._DefaultGeometry1D is created with dimension of the integer. If 2D tuple of integers is given, a cuqi.geometry._DefaultGeometry2D is created with dimensions of the tuple. If cuqi.geometry.Geometry object is given, it is used as the range geometry of the model.

  • domain_geometry (integer, a 1D or 2D tuple of integers, cuqi.geometry.Geometry or a tuple with items of any of the listed types) – If integer or 1D tuple of integers is given, a cuqi.geometry._DefaultGeometry1D is created with dimension of the integer. If 2D tuple of integers is given (and the forward model has one input only), a cuqi.geometry._DefaultGeometry2D is created with dimensions of the tuple. If cuqi.geometry.Geometry is given, it is used as the domain geometry. If tuple of the above types is given, a cuqi.geometry._ProductGeometry is created based on the tuple entries. This is used for models with multiple inputs where each entry in the tuple represents the geometry of each input.

  • gradient (callable function, a tuple of callable functions or None, optional) –

    The direction-Jacobian product of the forward model Jacobian with respect to the model input, evaluated at the model input. For example, if the forward model inputs are x and y, the gradient callable signature should be (direction, x, y), in that order, where direction is the direction by which the Jacobian matrix is multiplied and x and y are the parameters at which the Jacobian is computed.

    If the gradient function is a single callable function, it returns a 1D ndarray if the model has only one input. If the model has multiple inputs, this gradient function should return a tuple of 1D ndarrays, each representing the gradient with respect to each input.

    If the gradient function is a tuple of callable functions, each callable function should return a 1D ndarray representing the gradient with respect to each input. The order of the callable functions in the tuple should match the order of the model inputs.

  • jacobian (callable function, a tuple of callable functions or None, optional) –

    The Jacobian of the forward model with respect to the forward model input, evaluated at the model input. For example, if the forward model inputs are x and y, the jacobian signature should be (x, y), in that order, where x and y are the parameters at which the Jacobian is computed.

    If the Jacobian function is a single callable function, it should return a 2D ndarray of shape (range_dim, domain_dim) if the model has only one input. If the model has multiple inputs, this Jacobian function should return a tuple of 2D ndarrays, each representing the Jacobian with respect to each input.

    If the Jacobian function is a tuple of callable functions, each callable function should return a 2D ndarray representing the Jacobian with respect to each input. The order of the callable functions in the tuple should match the order of the model inputs.

    The Jacobian function is used to specify the gradient function by computing the vector-Jacobian product (VJP), here we refer to the vector in the VJP as the direction since it is the direction at which the gradient is computed. Either the gradient or the Jacobian can be specified, but not both.

Variables:
  • range_geometry – The geometry representing the range.

  • domain_geometry – The geometry representing the domain.

Example 1#

Consider a forward model \(F: \mathbb{R}^2 \rightarrow \mathbb{R}\) defined by the following forward operator:

\[F(x) = 10x_2 - 10x_1^3 + 5x_1^2 + 6x_1\]

The jacobian matrix of the forward operator is given by:

\[J_F(x) = \begin{bmatrix} -30x_1^2 + 10x_1 + 6 & 10 \end{bmatrix}\]

The forward model can be defined as follows:

import numpy as np
from cuqi.model import Model

def forward(x):
    return 10*x[1] - 10*x[0]**3 + 5*x[0]**2 + 6*x[0]

def jacobian(x): # Can use "x" or "wrt" as the input argument name
    return np.array([[-30*x[0]**2 + 10*x[0] + 6, 10]])

model = Model(forward, range_geometry=1, domain_geometry=2, jacobian=jacobian)

print(model(np.array([1, 1])))
print(model.gradient(np.array([1]), np.array([1, 1])))

Alternatively, the gradient information in the forward model can be defined by direction-Jacobian product using the gradient keyword argument.

This may be more efficient if forming the Jacobian matrix is expensive.

import numpy as np
from cuqi.model import Model

def forward(x):
    return 10*x[1] - 10*x[0]**3 + 5*x[0]**2 + 6*x[0]

def gradient(direction, x):
    # Direction-Jacobian product direction@jacobian(x)
    return direction@np.array([[-30*x[0]**2 + 10*x[0] + 6, 10]])

model = Model(forward, range_geometry=1, domain_geometry=2, gradient=gradient)

print(model(np.array([1, 1])))
print(model.gradient(np.array([1]), np.array([1, 1])))

Example 2#

Alternatively, the example above can be defined as a model with multiple inputs: \(x\) and \(y\):

import numpy as np
from cuqi.model import Model
from cuqi.geometry import Discrete

def forward(x, y):
    return 10 * y - 10 * x**3 + 5 * x**2 + 6 * x

def jacobian(x, y):
    return (np.array([[-30 * x**2 + 10 * x + 6]]), np.array([[10]]))

model = Model(
    forward,
    range_geometry=1,
    domain_geometry=(Discrete(1), Discrete(1)),
    jacobian=jacobian,
)

print(model(1, 1))
print(model.gradient(np.array([1]), 1, 1))
__init__(forward, range_geometry, domain_geometry, gradient=None, jacobian=None)#

Methods

__init__(forward, range_geometry, ...[, ...])

forward(*args[, is_par])

Forward function of the model.

gradient(direction, *args[, ...])

Gradient of the forward operator (Direction-Jacobian product)

Attributes

domain_dim

The dimension of the domain

domain_geometry

The geometry representing the domain of the model.

number_of_inputs

The number of inputs of the model.

range_dim

The dimension of the range

range_geometry

The geometry representing the range of the model.