Skip to content

feat(search): add multi-start gradient MAP searches (Adam/ADABelief/Lion) #1369

Description

@Jammy2211

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

  1. 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.
  2. autofit/__init__.py: export the three classes after LBFGS.
  3. pyproject.toml: add optax to the jax extra.
  4. 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).
  5. 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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions