symforce.opt.noise_models module#

class NoiseModel[source]#

Bases: object

Base class for whitening unwhitened residuals and/or computing their associated error in a least-squares problem.

abstract whiten(unwhitened_residual)[source]#

Whiten the residual vector.

Parameters:

unwhitened_residual (MatrixT) –

Return type:

MatrixT

static reduce(whitened_residual)[source]#

Take the sum of squares of the residual.

Parameters:

whitened_residual (MatrixT) –

Return type:

float

error(unwhitened_residual)[source]#

Return a scalar error.

Parameters:

unwhitened_residual (MatrixT) –

Return type:

float

class ScalarNoiseModel[source]#

Bases: NoiseModel

Base class for noise models that apply a whitening function to each element of the unwhitened residual

I.e. if f() is the whiten_scalar() function, each element of the whitened residual can be written as:

whitened_residual[i] = f(unwhitened_residual[i])
abstract whiten_scalar(x, bounded_away_from_zero=False)[source]#

A scalar-valued whitening function which is applied to each element of the unwhitened residual.

Parameters:
  • x (float) – A single element of the unwhitened residual

  • bounded_away_from_zero (bool) –

Return type:

float

whiten(unwhitened_residual)[source]#

Whiten the unwhitened residual vector by applying whiten_scalar() to each element.

Parameters:

unwhitened_residual (MatrixT) –

Return type:

MatrixT

whiten_norm(residual, epsilon=0.0)[source]#

Whiten the norm of the residual vector.

Let f(x) be the whitening function here, and let x be vector of residuals. We compute the whitened residual vector as w(x) = f(||x||)/||x|| * x. Then, the overall residual is later computed as ||w(x)|| == f(||x||), and so we’re minimizing the whitened norm of the full residual for each point.

Parameters:
  • residual (MatrixT) –

  • epsilon (float) –

Return type:

MatrixT

class IsotropicNoiseModel(scalar_information=None, scalar_sqrt_information=None)[source]#

Bases: ScalarNoiseModel

Isotropic noise model; equivalent to multiplying the squared residual by a scalar

The cost used in the optimization is:

cost = 0.5 * information * unwhitened_residual.T * unwhitened_residual

such that:

cost = 0.5 * whitened_residual.T * whitened_residual

The whitened residual is:

whitened_residual = sqrt(information) * unwhitened_residual
Parameters:
  • scalar_information (T.Optional[sf.Scalar]) – Scalar by which the least-squares error will be multiplied. In the context of probability theory, the information is the inverse of the variance of the unwhitened residual. The information represents the weight given to a specific unwhitened residual relative to other residuals used in the least-squares optimization.

  • scalar_sqrt_information (T.Optional[sf.Scalar]) – Square-root of scalar_information. If scalar_sqrt_information is specified, we avoid needing to take the square root of scalar_information. Note that only one of scalar_information and scalar_sqrt_information needs to be specified.

classmethod from_variance(variance)[source]#

Returns an IsotropicNoiseModel given a variance. Typically used when we treat the residual as a random variable with known variance, and wish to weight its cost according to the information gained by that measurement (i.e. the inverse of the variance).

Parameters:

variance (float) – Typically the variance of the residual elements. Results in cost cost = 0.5 * (1 / variance) * unwhitened_residual.T * unwhitened_residual

Return type:

IsotropicNoiseModel

classmethod from_sigma(standard_deviation)[source]#

Returns an IsotropicNoiseModel given a standard deviation. Typically used when we treat the residual as a random variable with known standard deviation, and wish to weight its cost according to the information gained by that measurement (i.e. the inverse of the variance).

Parameters:

standard_deviation (float) – The standard deviation of the residual elements. Results in cost = 0.5 * (1 / sigma^2) * unwhitened_residual.T * unwhitened_residual

Return type:

IsotropicNoiseModel

whiten_scalar(x, bounded_away_from_zero=False)[source]#

Multiplies a single element of the unwhitened residual by sqrt(information) so that the least-squares cost associated with the element is scaled by information.

Parameters:
  • x (float) – Single element of the unwhitened residual

  • bounded_away_from_zero (bool) – True if x is guaranteed to not be zero. Typically used to avoid extra ops incurred by using epsilons to avoid singularities at x = 0 when it’s known that x != 0. However, this argument is unused because there is no singularity at x = 0 for this whitening function.

Return type:

float

class DiagonalNoiseModel(information_diag=None, sqrt_information_diag=None)[source]#

Bases: NoiseModel

Noise model with diagonal weighting matrix

The cost used in the optimization is:

cost = 0.5 * unwhitened_residual.T * sf.diag(information_diag) * unwhitened_residual

where information_diag is a vector of scalars representing the relative importance of each element of the unwhitened residual.

The total cost is then:

cost = 0.5 * whitened_residual.T * whitened_residual

Thus, the whitened residual is:

whitened_residual = sf.diag(sqrt_information_diag) * unwhitened_residual

where sqrt_information_diag is the element-wise square root of information_diag.

Parameters:
  • information_diag (T.Optional[T.Sequence[sf.Scalar]]) – List of elements of the diagonal of the information matrix. In the context of probability theory, this vector represents the inverse of the variance of each element of the unwhitened residual, assuming that each element is an independent random variable.

  • sqrt_information_diag (T.Optional[T.Sequence[sf.Scalar]]) – Element-wise square-root of information_diag. If specified, we avoid needing to take the square root of each element of information_diag. Note that only one of information_diag and sqrt_information_diag needs to be specified.

classmethod from_variances(variances)[source]#

Returns an DiagonalNoiseModel given a list of variances of each element of the unwhitened residual

Typically used when we treat the unwhitened residual as a sequence of independent random variables with known variances.

Parameters:

variances (Sequence[float]) – List of the variances of each element of the unwhitened residual

Return type:

DiagonalNoiseModel

classmethod from_sigmas(standard_deviations)[source]#

Returns an DiagonalNoiseModel given a list of standard deviations of each element of the unwhitened residual

Typically used when we treat the unwhitened residual as a sequence of independent random variables with known standard deviations.

Parameters:

standard_deviations (Sequence[float]) – List of the standard deviations of each element of the unwhitened residual

Return type:

DiagonalNoiseModel

whiten(unwhitened_residual)[source]#

Whiten the residual vector.

Parameters:

unwhitened_residual (MatrixT) –

Return type:

MatrixT

class PseudoHuberNoiseModel(delta, scalar_information, epsilon=0.0)[source]#

Bases: ScalarNoiseModel

A smooth loss function that behaves like the L2 loss for small x and the L1 loss for large x.

The cost used in the least-squares optimization will be:

cost = sum( pseudo_huber_loss(unwhitened_residual[i]) )
cost = 0.5 * whitened_residual.T * whitened_residual

where the sum is taken over the elements of the unwhitened residual.

This noise model applies the square-root of the pseudo-huber loss function to each element of the unwhitened residual such that the resulting cost used in the least-squares problem is the pseudo-huber loss. The pseudo-huber loss is defined as:

pseudo_huber_loss(x) = delta^2 * ( sqrt( 1 + scalar_information * (x/delta)^2 ) - 1)

The whitened residual is then:

whitened_residual[i] = sqrt( 2 * pseudo_huber_loss(unwhitened_residual[i]) )
Parameters:
  • delta (sf.Scalar) – Controls the point at which the loss function transitions from the L2 to L1 loss. Must be greater than zero.

  • scalar_information (sf.Scalar) – Constant scalar weight that changes the steepness of the loss function. Can be considered the inverse of the variance of an element of the unwhitened residual.

  • epsilon (sf.Scalar) – Small value used to handle singularity at x = 0.

pseudo_huber_error(x)[source]#

Return the pseudo-huber cost function error for the argument x.

Parameters:

x (float) – argument to return the cost for.

Return type:

float

whiten_scalar(x, bounded_away_from_zero=False)[source]#

Applies a whitening function to a single element of the unwhitened residual such that the cost associated with the element in the least-squares cost function is the Pseudo-Huber loss function.

Parameters:
  • x (float) – Single element of the unwhitened residual

  • bounded_away_from_zero (bool) – True if x is guaranteed to not be zero. Typically used to avoid extra ops incurred by using epsilons to avoid singularities at x = 0 when it’s known that x != 0.

Return type:

float

class BarronNoiseModel(alpha, scalar_information, x_epsilon, delta=1, alpha_epsilon=None)[source]#

Bases: ScalarNoiseModel

Noise model adapted from:

Barron, Jonathan T. “A general and adaptive robust loss function.” Proceedings of the IEEE/CVF Conference on Computer Vision and Pattern Recognition. 2019.

This noise model applies a modified version of the “practical implementation” from Appendix B of the paper to each scalar element of an unwhitened residual. The Barron loss function is defined as:

barron_loss(x) = delta^2 * (b/d) * (( scalar_information * (x/delta)^2 / b + 1)^(d/2) - 1)

where:

b = |alpha - 2| + epsilon
d = alpha + epsilon if alpha >= 0 else alpha - epsilon

Here delta controls the point at which the loss function transitions from quadratic to robust. This is different from the original Barron loss function, and is designed to match the pseudo- huber loss function.

Thus, the cost used in the optimization will be:

cost = sum( barron_loss(unwhitened_residual[i]) )
cost = 0.5 * whitened_residual.T * whitened_residual

where the sum is taken over the elements of the unwhitened residual.

Thus, the whitened residual is:

whitened_residual[i] = sqrt( 2 * barron_loss(unwhitened_residual[i]) )
Parameters:
  • alpha (sf.Scalar) –

    Controls shape and convexity of the loss function. Notable values:

    • alpha = 2 -> L2 loss

    • alpha = 1 -> Pseudo-huber loss

    • alpha = 0 -> Cauchy loss

    • alpha = -2 -> Geman-McClure loss

    • alpha = -inf -> Welsch loss

  • delta (sf.Scalar) – Determines the transition point from quadratic to robust. Similar to “delta” as used by the pseudo-huber loss function.

  • scalar_information (sf.Scalar) – Scalar representing the inverse of the variance of an element of the unwhitened residual. Conceptually, we use scalar_information to whiten (in a probabilistic sense) the unwhitened residual before passing it through the Barron loss.

  • x_epsilon (sf.Scalar) – Small value used for handling the singularity at x == 0.

  • alpha_epsilon (T.Optional[sf.Scalar]) – Small value used for handling singularities around alpha.

static compute_alpha_from_mu(mu, epsilon)[source]#

Transform mu, which ranges from 0->1, to alpha by alpha=2-1/(1-mu). This transformation means alpha will range from 1 to -inf, so that the noise model starts as a pseudo-huber and goes to a robust Welsch cost.

Parameters:
  • mu (float) – ranges from 0->1

  • epsilon (float) – small value to avoid numerical instability

Returns:

sf.Scalar – alpha for use in the BarronNoiseModel construction

Return type:

float

barron_error(x)[source]#

Return the barron cost function error for the argument x.

Parameters:

x (float) – argument to return the cost for.

Returns:

Barron loss at value x

Return type:

float

whiten_scalar(x, bounded_away_from_zero=False)[source]#

Applies a whitening function to a single element of the unwhitened residual such that the cost associated with the element in the least-squares cost function is the Barron loss function.

Parameters:
  • x (float) – Single element of the unwhitened residual

  • bounded_away_from_zero (bool) –

Return type:

float