pyextal.jaxGeo.lm¶
Levenberg-Marquardt on the geometry, everything else held fixed.
Why Levenberg-Marquardt and not Adam¶
There are four parameters of very different stiffness – on tilted SrTiO3 data
the Hessian diagonal spans a factor of ~400 per unit, tiltx stiffest and
rotation softest – and some are coupled (gl with tilty at +0.6
there; gl also trades against thickness, which is held fixed here). A
first-order method with one learning rate handles that badly. With four
parameters the full Hessian is cheap – nine gradient evaluations by central
differences, or four Hessian-vector products exactly – and a damped Newton step
then converges in a handful of iterations, including along correlated
directions, where a pattern search, stepping one axis at a time, is slowest.
The damping is the usual one: solve (H + lambda diag|H|) dz = -g, accept the
step if the loss falls (and shrink lambda), otherwise grow lambda and try
again. Steps are additionally capped at trust units per parameter so the
frozen partition stays representative. The parameters are scaled so that one
unit is a chosen step (jaxGeo.geometry.units_for), which puts them on
comparable footing for both the cap and the solve.
Freezing the beam partition is the standard active-set treatment. The partition
only changes when a beam crosses the excitation cut, which moves the loss by a
Bethe-perturbation-sized amount, so it is re-run (beamcheck) only when the
geometry has moved refresh units, and once more at the end. The result after
that final refresh is the one that is kept, and it is kept only if it beats the
starting loss. Acceptance is judged on the training tiling, since a different
tiling averages over slightly different pixels.
The Hessian at the end gives the parameter correlations, which are printed: strongly correlated pairs are the ones the data does not separate.
Functions¶
|
Prints the parameter correlation matrix implied by a Hessian. |
|
Levenberg-Marquardt on the geometry, everything else held fixed. |
|
Compares the frozen-partition gradient with the real (rebuilt) loss. |
Module Contents¶
- pyextal.jaxGeo.lm.print_correlations(hess, names)¶
Prints the parameter correlation matrix implied by a Hessian.
- Parameters:
hess (np.ndarray) – (k, k) Hessian in scaled units.
names (list) – Parameter names, in order.
- pyextal.jaxGeo.lm.geometry_refine(x0, metadata, constants, make_obj, rebuild, epoch_loss_at, active, *, hessian='exact', lam=0.001, iters=8, trust=1.0, tol=1e-05, refresh=2.0)¶
Levenberg-Marquardt on the geometry, everything else held fixed.
- Parameters:
x0 (np.ndarray) – (4,) current geometry vector.
metadata (dict) – Metadata for
x0.constants (dict) – Bloch constants;
ndiagis updated by rebuilds and restored if the result is rejected.make_obj (callable) –
make_obj(x_ref, metadata) -> GeometryObjective, with the current parameters held fixed.rebuild (callable) –
rebuild(x) -> metadata– re-runsbeamcheckfor geometryx.epoch_loss_at (callable) –
epoch_loss_at(x, metadata) -> float– the training loss, on the training tiling.active (np.ndarray) – Indices of the refined parameters.
hessian (str) –
'exact'or'fd'.lam (float) – Initial damping.
iters (int) – Iteration limit.
trust (float) – Largest step per iteration, units per parameter.
tol (float) – Loss improvement below which the refinement stops, and by which the result must beat the start to be kept.
refresh (float) – Re-run
beamcheckonce the geometry has moved this many units from where the partition was built.
- Returns:
(x, metadata, loss, evals),losson the training tiling andevalscounting forward, gradient, HVP and rebuild calls.- Return type:
tuple
- pyextal.jaxGeo.lm.check_gradient(obj, make_obj, rebuild, names, h=0.05)¶
Compares the frozen-partition gradient with the real (rebuilt) loss.
Central differences of the full pipeline –
beamcheckrebuild included – athunits either side, against the JAX gradient at the same point, both on the objective’s tiling. The two agree if freezing the partition is harmless at this scale.- Parameters:
obj (GeometryObjective) – Built at the current geometry.
make_obj (callable) – As for
geometry_refine().rebuild (callable) – As for
geometry_refine().names (list) – Parameter names.
h (float) – Difference step, in units.