optim.CG

Contents

optim.CG#

class bartorch.optim.CG#

Bases:

Conjugate gradients for a least-squares problem with quadratic penalties.

Without terms the problem is

\[\min_x \; \| A x - y \|^2 + \lambda \| x \|^2\]

the ordinary Tikhonov-regularized least-squares problem. With terms it is

\[\min_x \; \| A x - y \|^2 + \lambda \| x \|^2 + \sum_i w_i \| G_i x - b_i \|^2\]

still a linear least-squares problem and so still this iteration.

Parameters:
  • lambda (float, default=0.0) – Tikhonov weight on the image itself, added to the normal operator.

  • terms (Tikhonov or iterable of Tikhonov, default=None) – Quadratic penalties with an operator, a bias, or both. See Tikhonov.

  • maxiter (int, default=30)

  • tol (float, default=0.0) – Stop once the residual of the normal equations is at most tol * ||A^H y||. Zero, BART’s default, runs every iteration.

  • cclambda (float, default=0.0) – Weight of an identity added to the normal operator.

  • precond (LinearOperator, default=None) – Left preconditioner, lsqr2_create’s precond_op: chained onto the normal operator and onto the adjoint, so the iteration sees M(A^H A + lambda) x = M A^H y. Must be positive definite – BART composes it without symmetrizing. BART’s own reconstructions pass none.

Notes

BART’s conjugate gradients takes one weight and nothing else: iter2_conjgrad asserts that it is handed no regularizing operators and no biases, and lsqr2_create builds A^H A + lambda I. So the terms are not passed to it – they are built into the operator it is given, by stacking them under the encoding.

Examples

>>> CG(maxiter=30)(kspace, A)
>>> CG(terms=Tikhonov(0.1, bias=prior))(kspace, A)
>>> CG(terms=[Tikhonov(0.1, operator=G), Tikhonov(0.01)])(kspace, A)
__call__()#

Solve, and with steps say how many iterations it took.

An alternating-direction solver budgets by this count, which is not otherwise visible from outside the library.

When y carries a gradient the solve is recorded: the forward pass is the same iteration and the same bits, and the backward pass is another solve with the same operator, as bartorch.optim._autograd describes. A solve can therefore stand inside an unrolled network – as the data-consistency layer of a MoDL, for instance – and not only at the end of one.