Overview
Phase 1 of promoting the benchmark-winning multi-start gradient MAP optimizer to first-class PyAutoFit searches. The wide multi-start first-order gradient method reliably recovers the truth basin where every single-start, line-search and second-order method fails (autolens_workspace_developer PR#96+#98, Phase-3 complete: nothing beats multi-start Adam on the NNLS-kinked lens likelihood). This grows the mle/ search library alongside Drawer / BFGS / LBFGS.
Plan
- Add
AbstractMultiStartGradient(AbstractMLE) under autofit/non_linear/search/mle/multi_start_gradient/, owning the shared N-broad-start, vmapped value_and_grad, optax-update MAP loop against the library-agnostic af.Fitness seam.
- Ship three concrete rule-classes —
af.MultiStartAdam (lr 1e-2, certified best), af.MultiStartADABelief (lr 1e-2, tied), af.MultiStartLion (lr 1e-3) — each a thin subclass fixing its optax factory + default lr; export in autofit/__init__.py.
- Return best-basin MAP + per-start basin diagnostics through the standard
Samples/Result contract, with search-internal save/resume.
- Add
optax as a jax-extra dependency with a lazy, clear-error import.
- Library unit tests numpy-only (plumbing); JAX end-to-end truth-basin recovery in autofit_workspace_test behind the library-first gate.
Detailed implementation plan
Affected Repositories
- PyAutoFit (primary)
- autofit_workspace_test (JAX end-to-end validation, follows library merge)
Branch Survey
| Repository |
Current Branch |
Dirty? |
| ./PyAutoFit |
main |
clean |
| ./autofit_workspace_test |
main |
clean |
Suggested branch: feature/multi-start-gradient-search
Note: PyAutoFit is softly claimed by database-latent-wheel-load (PyAutoFit#1368, merged; only corrective release-validation remains). Human-approved to proceed in a parallel worktree — no real source collision.
Implementation Steps
autofit/non_linear/search/mle/multi_start_gradient/{__init__.py,search.py}:
AbstractMultiStartGradient(AbstractMLE) with __init__(n_starts=48, n_steps=300, learning_rate=None→_default_lr, start_low=0.15, start_high=0.85, initializer, iterations_per_*_update, silence, session, **kwargs) and class attrs _optax_factory, _default_lr.
_fit(model, analysis): Fitness(model, analysis, fom_is_log_likelihood=False) with use_jax_vmap when analysis._use_jax; lazy import optax; broad unit-space starts → model.vector_from_unit_vector(u, xp=jnp), keep finite-gradient starts; jax.jit(jax.vmap(jax.value_and_grad(neg_log_posterior))); optax loop; track global-best + per-start finals; save_search_internal for resume — mirroring mle/bfgs/search.py.
samples_via_internal_from: best-basin MAP as max-lik Sample, per-start finals as diagnostic samples; samples_info carries per-start basin stats.
MultiStartAdam / MultiStartADABelief / MultiStartLion subclasses.
autofit/__init__.py: export the three classes after LBFGS.
pyproject.toml: add optax to the jax extra.
test_autofit/non_linear/search/mle/test_multi_start_gradient.py: numpy-only — start generation/filtering, Samples build, resume round-trip, config parsing (simple analytic objective; no JAX in the library suite).
- autofit_workspace_test: end-to-end script —
MultiStartAdam recovers a known truth basin on a JAX likelihood; asserts best-basin params.
Key Files
autofit/non_linear/search/mle/bfgs/search.py — structural analogue (Abstract + concrete subclasses, samples_via_internal_from, resume).
autofit/non_linear/fitness.py — the af.Fitness seam (_jit/_vmap/_grad, use_jax_vmap).
autofit/mapper/prior_model/abstract.py::vector_from_unit_vector — jax-traceable unconstrained transform.
autolens_workspace_developer/searches_minimal/{gpu_multi_start_adam,_grad_setup}.py — reference algorithm (port algorithm only; PyAutoFit must not import autoarray/autolens).
Out of scope
Line-search / second-order methods (L-BFGS/BFGS/NCG/LM/Gauss-Newton) — all failed the benchmark on the NNLS-kinked objective.
Follow-up phases
- Phase 2 — config + packaged defaults (optax rule / N / lr / step-count as first-class packaged config).
- Phase 3 — autofit_workspace examples on an imaging lens fit (Opus-authored prose).
Original Prompt
Click to expand starting prompt
Phase 1 of promoting the multi-start gradient MAP optimizer (benchmark winner, autolens_workspace_developer PR#96+#98, Phase-3 complete) to first-class PyAutoFit searches. Adds AbstractMultiStartGradient(AbstractMLE) + af.MultiStartAdam / af.MultiStartADABelief / af.MultiStartLion, running N broad multi-starts vmapped over the af.Fitness seam with a fixed self-normalised optax update per start, returning best-basin MAP + per-start diagnostics through the standard samples/result contract. optax added as a jax-extra dep. Library unit tests numpy-only; JAX end-to-end truth-basin validation in autofit_workspace_test. Line-search/second-order methods explicitly out of scope. Follow-ups: Phase 2 config/defaults, Phase 3 workspace examples.
Overview
Phase 1 of promoting the benchmark-winning multi-start gradient MAP optimizer to first-class PyAutoFit searches. The wide multi-start first-order gradient method reliably recovers the truth basin where every single-start, line-search and second-order method fails (autolens_workspace_developer PR#96+#98, Phase-3 complete: nothing beats multi-start Adam on the NNLS-kinked lens likelihood). This grows the
mle/search library alongsideDrawer/BFGS/LBFGS.Plan
AbstractMultiStartGradient(AbstractMLE)underautofit/non_linear/search/mle/multi_start_gradient/, owning the shared N-broad-start, vmappedvalue_and_grad, optax-update MAP loop against the library-agnosticaf.Fitnessseam.af.MultiStartAdam(lr 1e-2, certified best),af.MultiStartADABelief(lr 1e-2, tied),af.MultiStartLion(lr 1e-3) — each a thin subclass fixing its optax factory + default lr; export inautofit/__init__.py.Samples/Resultcontract, with search-internal save/resume.optaxas a jax-extra dependency with a lazy, clear-error import.Detailed implementation plan
Affected Repositories
Branch Survey
Suggested branch:
feature/multi-start-gradient-searchNote: PyAutoFit is softly claimed by
database-latent-wheel-load(PyAutoFit#1368, merged; only corrective release-validation remains). Human-approved to proceed in a parallel worktree — no real source collision.Implementation Steps
autofit/non_linear/search/mle/multi_start_gradient/{__init__.py,search.py}:AbstractMultiStartGradient(AbstractMLE)with__init__(n_starts=48, n_steps=300, learning_rate=None→_default_lr, start_low=0.15, start_high=0.85, initializer, iterations_per_*_update, silence, session, **kwargs)and class attrs_optax_factory,_default_lr._fit(model, analysis):Fitness(model, analysis, fom_is_log_likelihood=False)withuse_jax_vmapwhenanalysis._use_jax; lazyimport optax; broad unit-space starts →model.vector_from_unit_vector(u, xp=jnp), keep finite-gradient starts;jax.jit(jax.vmap(jax.value_and_grad(neg_log_posterior))); optax loop; track global-best + per-start finals;save_search_internalfor resume — mirroringmle/bfgs/search.py.samples_via_internal_from: best-basin MAP as max-likSample, per-start finals as diagnostic samples;samples_infocarries per-start basin stats.MultiStartAdam/MultiStartADABelief/MultiStartLionsubclasses.autofit/__init__.py: export the three classes afterLBFGS.pyproject.toml: addoptaxto the jax extra.test_autofit/non_linear/search/mle/test_multi_start_gradient.py: numpy-only — start generation/filtering,Samplesbuild, resume round-trip, config parsing (simple analytic objective; no JAX in the library suite).MultiStartAdamrecovers a known truth basin on a JAX likelihood; asserts best-basin params.Key Files
autofit/non_linear/search/mle/bfgs/search.py— structural analogue (Abstract + concrete subclasses,samples_via_internal_from, resume).autofit/non_linear/fitness.py— theaf.Fitnessseam (_jit/_vmap/_grad,use_jax_vmap).autofit/mapper/prior_model/abstract.py::vector_from_unit_vector— jax-traceable unconstrained transform.autolens_workspace_developer/searches_minimal/{gpu_multi_start_adam,_grad_setup}.py— reference algorithm (port algorithm only; PyAutoFit must not import autoarray/autolens).Out of scope
Line-search / second-order methods (L-BFGS/BFGS/NCG/LM/Gauss-Newton) — all failed the benchmark on the NNLS-kinked objective.
Follow-up phases
Original Prompt
Click to expand starting prompt
Phase 1 of promoting the multi-start gradient MAP optimizer (benchmark winner, autolens_workspace_developer PR#96+#98, Phase-3 complete) to first-class PyAutoFit searches. Adds
AbstractMultiStartGradient(AbstractMLE)+af.MultiStartAdam/af.MultiStartADABelief/af.MultiStartLion, running N broad multi-starts vmapped over theaf.Fitnessseam with a fixed self-normalised optax update per start, returning best-basin MAP + per-start diagnostics through the standard samples/result contract. optax added as a jax-extra dep. Library unit tests numpy-only; JAX end-to-end truth-basin validation in autofit_workspace_test. Line-search/second-order methods explicitly out of scope. Follow-ups: Phase 2 config/defaults, Phase 3 workspace examples.