fix: EP projection — transform samples to base space + use log weights#1383
Merged
Conversation
…1382) Two stacked defects made every sampler-driven EP factor update project its posterior to a message pinned near a prior bound (boundary attractor -> cavity poisoning -> hierarchical sigma-collapse, flagged as F10 by the EP diagnostics): 1. TransformedMessage.project forwarded PHYSICAL samples straight into the base message's moment match without applying the transform stack — the primary defect: even equal-weighted samples clustered at 2.05 inside UniformPrior(1.5, 3.0) projected to mean 2.97. It now maps samples through self._transform first, exactly as @Transform does for pdf and friends (weights need no Jacobian: a weighted empirical distribution transforms its atoms, not its weights). 2. Result.projected_model passed LINEAR importance weights into a moment match that requires LOG weights (w = exp(log_w - max)), near-uniformly weighting the whole nested run. It now converts (zero weights -> -inf -> drop out) and raises on all-zero weights. Prior.project's kwarg is renamed to log_weight_list so the expected scale is unambiguous. Regression test: nested-sampling-shaped weighted samples through a UniformPrior must project to the posterior moments, not the prior spread (fails on either defect alone). Full test_autofit: 1494 passed, 1 skipped. End-to-end forensics and repro: Jammy2211/slope_hierarchy#1 (RAL probe 330591: factor fit slope 2.0448 vs projected message 2.9875). Co-Authored-By: Claude Fable 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.
Fixes #1382.
What was broken
Every sampler-driven EP factor update projects its posterior samples into a mean-field message via
Result.projected_model. Two stacked defects made that projection land near a prior bound with spuriously tiny std — poisoning the EP cavity and driving the F10 sigma-collapse on any hierarchical graph (the #1335 diagnostics flagged the collapse correctly; the cause was upstream of them):TransformedMessage.projectnever transformed its samples (primary). Physical samples went straight into the base (e.g. logit-normal) message's moment match. Even equal-weighted samples clustered at 2.05 insideUniformPrior(1.5, 3.0)projected to mean 2.97.Result.projected_modelpassed linear importance weights into a log-weight moment match (w = exp(log_w − max)), near-uniformly weighting the entire nested-sampling run, prior-exploration phase included.The fix
TransformedMessage.projectmaps samples throughself._transformbefore the base moment match — exactly as@transformdoes forpdfand friends. No Jacobian on the weights: a weighted empirical distribution transforms its atoms, not its weights.Result.projected_modelconvertsweight_listto log weights (zeros → −inf → drop out; all-zero raisesValueError).Prior.project's kwarg renamedweights→log_weight_listwith the scale requirement documented, so the ambiguity that hid defect 2 can't recur.Tests
test_projected_model_moments: nested-sampling-shaped weighted samples (broad negligible-weight prior phase + concentrated posterior) through aUniformPriormust project to the posterior moments — fails on either defect alone.test_autofit: 1494 passed, 1 skipped.Real-case evidence & post-merge validation
Found by the slope_hierarchy science project deliberately exercising the 2026-07 EP wave on a realistic lensing case (full forensics: Jammy2211/slope_hierarchy#1). Smoking gun (RAL probe, 1 imaging lens × 1 EP step): the factor's own Nautilus fit found
slope = 2.0448 (2.015, 2.075)while its projected message was2.9875 ± 0.011; with this branch the same projection probe lands at 2.0493. After merge, slope_hierarchy reruns its 5-lens EP fit for the EP-vs-NUTS parity check (its goal 2, currently blocked on this PR).Note:
weight_list-as-log may have silently biased historic sampler-driven EP results (e.g. concr-era H0 runs) — worth keeping in mind when comparing against old EP outputs.🤖 Generated with Claude Code