Repository navigation
fix: tie-robust border-ellipse extents so jit gradients are correct - #672
Merged
Merged
Conversation
…671) ellipse_params_via_border_pca_from took the semi-axes as max(|x'|) and max(|y'|). A lens centred on the mask's symmetry centre traces the border into exact +/- pairs, so both maxima tie; JAX's max gradient finds tied entries by equality, which is unstable under jit, and the reverse-mode gradient of b came out 2x / 0.5x its true value (eager was correct). Take the element at the argmax instead (max_at_argmax_from): same values, one-hot gradient under eager and jit. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
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
Fixes a wrong JAX gradient through the border relocator when the lens is centred on the mask's symmetry centre. This is the case for every cell evaluated at the prior medians. Closes #671.
What goes wrong:
ellipse_params_via_border_pca_fromsizes the relocation ellipse witha = max(|x′|)andb = max(|y′|). A point-symmetric lens (Isothermal + external shear) centred on the symmetry centre of the mask traces the border into exact ± pairs, so both maxima are exact ties. JAX'smaxgradient shares itself among the entries equal to the result. Underjit, XLA can recompute the operand inside a fused graph with different rounding, so that equality test is unstable. The reverse-mode gradient ofbcame out 2× or 0.5× its true value, while eager mode was correct. Every pixelized-source likelihood withuse_border_relocator=Trueinherits this.Measured (jitted
Fitness,jax_testimaging,RectangularRTUAdaptImage39x39, MGE-60 lens light, exact prior medians):mass.einstein_radiusmass.ell_comps_0mass.ell_comps_1Stage bisection: the traced grid had identical tangents under eager,
jitand FD. The relocated grid diverged only underjitreverse mode, and inside it onlyb(eager 0.5392,jit1.0908, FD 0.5392).Fix: a new helper
max_at_argmax_fromtakes the element at the argmax instead of amaxreduction, so the whole gradient lands on one point, identically under eager andjit. Values are bit-identical to before. At a genuine tie, any single element's derivative is a valid one-sided derivative of the maximum.Not changed: the kernel-CDF per-axis
min/maxandstd(axis=0).min()ininterpolator/rectangular.pyare the same kind of reduction. They showed no eager/jitdivergence in axis-aligned and round configurations, which do produce exact ties, so they are left as they are.About the original #671 symptom (|g| ≈ 2e9 on the HST fiducial): that part is not a library bug. The 141x141 grid at pixelization over-sampling 1 has a point exactly at the Isothermal centre, where the
psisoftening (a 1e-8 core) makes the true derivative about 1e8, which FD cannot resolve. The evaluation-point fix belongs to the profiling campaign (autolens_profiling#509). Diagnosis is on #671.API Changes
Bug fix to JAX gradients only; numerical values are unchanged.
autoarray.inversion.mesh.border_relocator.max_at_argmax_from(values, xp=np), a tie-robust maximum.ellipse_params_via_border_pca_fromuses it for the semi-axesaandb. Same values, correctedjitgradients.See full details below.
Test Plan
test__max_at_argmax_from__tied_maximum_gradient_lands_on_one_element: one-hot gradient on a tied maximum, eager andjit.jnp.maxfails it with a 0.5/0.5 split.test_autoarraysuite: 2268 passed, 4 xfailed.Science/scratch/rectangular_gradient_rtu_sparse_2026-11-02/.Full API Changes (for automation & release notes)
Added
autoarray.inversion.mesh.border_relocator.max_at_argmax_from(values, xp=np): maximum of a 1D array taken asvalues[xp.argmax(values)], so its gradient is one-hot even at ties.Changed
ellipse_params_via_border_pca_from: semi-axesa,bcomputed viamax_at_argmax_from. Values are identical. Reverse-mode gradients underjitare now correct at tied extents (previously 2× / 0.5× off).Migration
Generated by the PyAutoLabs agent workflow.
🤖 Generated with Claude Code