Skip to content

fix: AnalysisImaging.log_likelihood_function CPU branch returns figure_of_merit (not log_likelihood)#504

Merged
Jammy2211 merged 1 commit into
mainfrom
feature/cpu-pixelization-log-evidence-bug
May 12, 2026
Merged

fix: AnalysisImaging.log_likelihood_function CPU branch returns figure_of_merit (not log_likelihood)#504
Jammy2211 merged 1 commit into
mainfrom
feature/cpu-pixelization-log-evidence-bug

Conversation

@Jammy2211
Copy link
Copy Markdown
Collaborator

Summary

  • The CPU branch of AnalysisImaging.log_likelihood_function returned fit.log_likelihood while the JAX branch returned fit.figure_of_merit. For pixelization (inversion) fits these differ by the regularization log-det terms of the Bayesian log evidence.
  • As a result, any nested sampler driven by the CPU path was optimising a chi²-only target instead of the log evidence — and drifted toward outer_coefficient ≈ 0 (noise-overfit, degenerate "no regularization" mode). JAX runs of the same model converged to the physical Bayesian-evidence maximum.
  • Fix: return fit.figure_of_merit from both branches. For purely parametric fits this is a no-op because figure_of_merit == log_likelihood; for inversion fits the search now uses the mathematically correct objective.

Test plan

  • New regression test test__log_likelihood_function__returns_figure_of_merit_for_pixelization exercises a Rectangular Pixelization with Constant regularization, asserts analysis.log_likelihood_function(instance) == fit.figure_of_merit, and verifies the two quantities genuinely differ (so the test isn't a tautology).
  • Existing test__figure_of_merit__matches_correct_fit_given_galaxy_profiles (parametric Sersic) still passes because figure_of_merit == log_likelihood when there's no inversion.
  • Full test_autolens/imaging/model/test_analysis_imaging.py passes (5/5).
  • End-to-end verification on a simulated lens: Nautilus + CPU sparse + 4-core converges from the degenerate mode (einstein_radius=0.997, outer_coefficient=0.000) to the physical mode (einstein_radius=1.001, outer_coefficient=95.6), matching the JAX baseline to within numerical precision.

Impact

  • All previous Nautilus / DynestyStatic / nested-sampler lens-imaging fits run on CPU with a pixelization source were optimising the wrong objective. Re-runs may produce different (correct) posteriors.
  • JAX runs are unaffected — they were already using figure_of_merit.
  • Non-pixelization (parametric-only) runs are unaffected — figure_of_merit == log_likelihood for those.

🤖 Generated with Claude Code

…ging.log_likelihood_function

The CPU branch returned fit.log_likelihood while the JAX branch returned
fit.figure_of_merit. For pixelization (inversion) fits these differ by the
regularization log-det terms, so any nested sampler driven by the CPU path
optimised a chi^2-only target and drifted toward outer_coefficient ~ 0
(noise-overfit), while JAX runs converged to the physical Bayesian-evidence
maximum.

Add a regression test that exercises a Rectangular Pixelization with
Constant regularization so the two quantities differ; the existing
parametric-Sersic test still passes because fom == log_likelihood when
there is no inversion.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@Jammy2211 Jammy2211 merged commit 3c4fcc0 into main May 12, 2026
5 checks passed
@Jammy2211 Jammy2211 deleted the feature/cpu-pixelization-log-evidence-bug branch May 12, 2026 17:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant