NonlinearLeastSquares#
- class torchsim.NonlinearLeastSquares(acquisition=None, *, bounds=None, initial=None, loop=None)[source]#
Bases:
EstimatorLevenberg-Marquardt, stepping every voxel together.
Where a dictionary spans a grid whose size is the product of the parameter ranges, a nonlinear fit walks downhill from a starting guess and pays nothing for a third parameter beyond a third column of the Jacobian. What it gives up is the guarantee: it finds a local minimum of the residual, and which one depends on where it started.
This is an
Estimatorface onGaussNewton, and holds no algorithm of its own. Fitting images voxel by voxel and reconstructing maps from k-space are the same loop over the sameModelOperatorwith nothing encoding the voxels together, so what is here is only the adaptation: where the fit starts, and what the training set is for.The loop it runs by default carries a per-voxel trust region, so every voxel takes its step in the same pass, carries its own damping, accepts or rejects on its own, and drops out when it has converged – and the remaining ones close up, so late iterations cost only what is left.
- Parameters:
acquisition (Simulator, optional) – The sequence being inverted: a simulator that ships with TorchSim, one written by subclassing
Simulator, or any otherSimulator. Every tissue property that is neither unknown nor measured separately is fixed on it beforehand, with the constructor orbind(). Leave it out to fit from signals handed tofit()directly.bounds (mapping, optional) –
{name: (low, high)}, either endNonefor unbounded. A bound is kept by fitting a transformed variable rather than by clipping a result, so no iterate ever leaves the interval and the bound cannot be sitting exactly on the answer. It also puts every parameter on the same scale whatever its units, which is what the damping term assumes.initial (mapping, optional) –
{name: value}to start from, which must be strictly inside that property’s bound. Without one,fit()takes the median of the parameters the training set drew.loop (GaussNewton, optional) – The solve to run, and where every knob it has lives – how many steps, how the damping moves, which tolerance stops a voxel. The default is Levenberg-Marquardt: a
TrustRegionoverdirect(), twenty steps.
Notes
Equality constraints are written into the model, not declared here. A constraint that fixes one parameter in terms of the others removes a degree of freedom, so the way to impose it is to not have that freedom: write the model in terms of the parameters that remain. For a fat-water fit where the two fractions must sum to one, make the fat fraction
fthe only unknown and write water as1 - finside the model. The constraint then holds identically at every iterate, rather than being restored after each one.The solve is iterative and runs without building a graph, so an estimate carries no gradient with respect to the measurement.
Examples
fit = NonlinearLeastSquares( FSESimulator(ESP=5.0, TR=1800.0, flip=train), bounds={"T2": (1.0, 500.0)}, ).fit(T1=(200.0, 3000.0), T2=(10.0, 300.0)) maps = fit.map(volume)
A solve that needs more room, or a different one entirely:
NonlinearLeastSquares( bounds={"T2": (1.0, 500.0)}, loop=GaussNewton(TrustRegion(tau=1e-3), solve=direct, max_iterations=60), )
Methods
fitFit the estimator over a sampling of the tissue it will meet.
from_coefficientsMap coefficients that are already in this estimator's basis.
mapEstimate the tissue a measurement came from.
training_setSimulate a training set: signals, unknowns, and knowns.
uncertainty_ofThe standard deviation the measurement noise leaves on each map.
- iterations#
Steps the last solve took, and how many voxels ran out of them.
- property fitted#
Whether a model and a starting point are both in place.