feat(autofit): multi-start gradient auto-convergence (phase 1)#1407
Merged
Jammy2211 merged 1 commit intoJul 21, 2026
Merged
Conversation
…earches Add a MultiStartGradientConvergence settings object (mirroring AutoCorrelationsSettings) so MultiStartAdam/ADABelief/Lion/Prodigy stop early once the global-best figure-of-merit plateaus, defaulting on so users no longer hand-tune n_steps. n_steps remains a hard ceiling. The plateau check runs per-step (fom_history updates every step) while checkpointing stays at the iterations_per_full_update boundary, so early-stop works with the default single-chunk cadence. Skipped when resurrect=True (pixelized regime). Carries stop_reason in search_internal for resume and the phase-2 results contract. Phase 1 of 2 (results-contract + aggregator hardening follows). Refs #1406. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LSEf7D5urqPgvffKBqzPsF
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Give the multi-start gradient searches (
MultiStartAdam/MultiStartADABelief/MultiStartLion/MultiStartProdigy) a first-class auto-convergence (early-stopping) mode, default ON, so users no longer hand-tunen_steps. PreviouslyAbstractMultiStartGradientran a fixedn_stepsbudget with no convergence criterion.n_stepsnow serves as a hard ceiling / max budget (the search never runs forever).Mirrors the
AutoCorrelationsSettingsprecedent (Emcee/Zeus early-stop): a newMultiStartGradientConvergencesettings object withcheck_for_convergence=True, a plateau check on the global best figure-of-merit over a trailing window (rtol/atol+min_steps), and anis_test_mode()shrink hook. The check runs per-step (the best-fom history updates every step) while checkpointing/visualization stays at theiterations_per_full_updateboundary — so early-stopping works even with the default single-chunk update cadence (iterations_per_full_update=None), at the cost of a cheap NumPy plateau check per step.Scope: parametric sources only (MGE / Sersic). Pixelized is out of scope — its best-fom climbs in long plateaus punctuated by breakthrough jumps, which a plateau check would false-stop on. So the check is skipped when
resurrect=True(the pixelized regime), where the search leans on then_stepsceiling — behaviour there is unchanged.Phase 1 of 2. Phase 2 (results contract:
converged/stop_reasoninsamples_info, the fom_history convergence-trace artifact, and aggregator hardening for variable-length runs) follows. Successor to the multi-start gradient v2 work (#1398/#1400).JAX compile-cache on recall: the persistent compilation cache is already default-on via
autonerves(JAX_COMPILATION_CACHE_DIR), so a resumed search reuses the disk-cached compiledvalue_and_gradrather than recompiling. This change keeps the resume path's traced computation identical, so the cache still hits; the empirical early-stop → resume → no-recompile check is theautofit_workspace_testfollow-up.API Changes
Additive, plus one default-behaviour change. Added:
af.MultiStartGradientConvergencesettings object and aconvergence=parameter on all four multi-start gradient searches (defaults to auto-convergence ON). Changed behaviour: the searches now stop early by default once the global-best figure-of-merit plateaus (parametric regime);n_stepsremains a hard ceiling. No migration required — passconvergence=af.MultiStartGradientConvergence(check_for_convergence=False)to restore the previous always-run-to-n_stepsbehaviour.resurrect=Truebehaviour is unchanged (check skipped).See full details below.
Test Plan
python -m pytest test_autofit/in the worktree → 1521 passed, 1 skippedmin_steps/window length, relative tolerance, disabled + non-finite, dict round-trip)autofit_workspace/scripts/searches/mle.pyruns end-to-end through the new code (early-stop fires; exit 0)autofit_workspace_testJAX validation: MGE early-stop + resume-asserts-no-recompile (phase-1 workspace follow-up)Full API Changes (for automation & release notes)
Added
af.MultiStartGradientConvergence(check_for_convergence=True, window=50, rtol=1e-4, atol=1e-3, min_steps=100)— auto-convergence (early-stopping) settings for the multi-start gradient searches; exposescheck_if_converged(fom_history)(global-best plateau over the trailingwindow).convergenceparameter onAbstractMultiStartGradient.__init__(inherited byMultiStartAdam/MultiStartADABelief/MultiStartLion/MultiStartProdigy);Nonebuilds the defaultMultiStartGradientConvergence().Changed Behaviour
n_stepsremains a hard ceiling / max budget.resurrect=True(pixelized regime) — that path runs to then_stepsceiling exactly as before.search_internal(and the on-disk checkpoint) now carriesstop_reason("converged"|"max_steps"), so a resumed already-converged search short-circuits rather than running more steps.Migration
n_stepsbehaviour:search = af.MultiStartAdam(..., convergence=af.MultiStartGradientConvergence(check_for_convergence=False)).Validation checklist (--auto run — plan was not pre-approved)
searches/mle.py, the one affected curated script, runs end-to-end; early-stop fires) · review self-CLEAN (additive + one default-behaviour change; faculty runs on the committed diff) · Heart RED — two reasons, both pre-existing and unrelated ("PyAutoFit: 2 commit(s) behind origin","PyAutoLens: 1 uncommitted source change(s)"), human-waived contemporaneously via AskUserQuestionGenerated by the PyAutoLabs agent workflow.