fix(latent): degenerate latent edge cases (quantile n=1, latent exceptions, anti-correlated NaNs)#1311
Merged
Merged
Conversation
…t exceptions, anti-correlated NaNs) Follow-up to the per-batch latent NaN-masking fix; a sanity probe surfaced three further break scenarios in the latent pipeline: A. quantile() crashed for a single weighted sample — np.cumsum(sw)[:-1] is empty for n=1 and cdf[-1] raised IndexError. General Samples bug, exposed when latent masking leaves one finite survivor with weight <= 0.99. Fix: return the sample's value for every quantile when n==1. B. A latent function raising a non-FitException crashed the whole latent pass. _safe_compute (numpy) only caught FitException; the JAX jit per-sample path had no guard. Fix: broaden both to catch any Exception -> NaN row (dropped by the mask). vmap path documented as raise-free (traced once). C. Anti-correlated NaNs (every sample NaN in some latent) dropped all samples -> None, losing all latent output. Fix: greedy column-salvage — sacrifice the worst-coverage latent(s) and retain the maximal-coverage ones with their finite samples. Normal fits are unchanged (stop on first finite row). Adds unit tests in test_autofit for all three. Co-Authored-By: Claude Opus 4.8 (1M context) <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
Follow-up to the per-batch latent NaN-masking fix. A 13-scenario sanity probe surfaced three further break scenarios in the latent pipeline — one real crash, one robustness gap, one silent total-loss of latent output. All three are fixed with unit-test coverage.
API Changes
No signature changes. Behaviour:
quantile()now handles a single sample;compute_latent_samplestolerates latent functions that raise (any exception → dropped sample) and salvages anti-correlated-NaN cases instead of returningNone.See full details below.
Test Plan
pytest test_autofit/non_linear/samples/test_pdf.py test_autofit/analysis/test_latent_variables.py— 24 passedpytest test_autofit/non_linear --ignore=.../nss— 265 passed (NSS = pre-existing optional-dep ImportErrors)Full API Changes (for automation & release notes)
Changed Behaviour
autofit.non_linear.samples.pdf.quantile— returns the sample's value for every requested quantile when given a single sample (previously raisedIndexErrorvianp.cumsum(sw)[:-1]/cdf[-1]). Affects all callers (median_pdf,values_at_sigma), not just latents.autofit.non_linear.analysis.Analysis.compute_latent_samples:FitException) now yields a NaN row (dropped by masking) instead of crashing the latent pass — numpy_safe_computeand the JAXjitper-sample path both guard. Thevmappath is documented as raise-free (single traced call).None). Normal fits are unchanged.🤖 Generated with Claude Code