Skip to content

Add L2 anchor semantics (initial/uniform/design); fix the flaky refit ESS test - #309

Merged
MaxGhenis merged 1 commit into
mainfrom
l2-anchor-semantics
Jul 5, 2026
Merged

Add L2 anchor semantics (initial/uniform/design); fix the flaky refit ESS test#309
MaxGhenis merged 1 commit into
mainfrom
l2-anchor-semantics

Conversation

@juaristi22

Copy link
Copy Markdown
Collaborator

Closes #307. Follow-up to #283; experimental evidence in #285 (full results comment incoming).

Why

The l2_lambda penalty divides by a reference vector, and that choice decides which way the penalty pulls: under mass="conserve" its constrained optimum is w ∝ anchor². Anchored at heterogeneous starting weights the penalty concentrates rather than spreads. The post-L0 refit starts from the selection stage's concentrated calibrated weights, so the refit_l2_lambda knob shipped in #283 is a trap at its default anchor: on the full 337k-record US surface a refit penalty of λ=1e-3 collapsed ESS from 8,408 to 1,057 instead of raising it (see #285 sweep data).

What

  • calibrate(..., l2_anchor="initial"|"uniform")"uniform" divides by the mean starting weight, making the penalty a direct 1/ESS control from any starting distribution. l2_anchor_weights is the explicit-vector seam for anchors the frame can't express, recorded in options with a free-form provenance label.
  • refit_l0_selection / calibrate_l0_refit gain "design": anchor the refit at the pre-selection initial weights of surviving records ("stay near the survey design") — derived from the selection result, no extra inputs. At a fresh selection "design" collapses to "initial". refit_l2_anchor follows the refit_epochs inherit-or-override pattern; invalid anchors fail before the expensive selection stage.
  • Direction contract pinned where it's decidable: from heterogeneous starts (ESS 29.3 of 160), the initial anchor drives ESS below 0.6× the start while the uniform anchor drives it above 1.4×, at healthy loss — margins orders of magnitude above run-to-run noise.

The #307 fix

test_refit_l0_selection_threads_l2_lambda_to_refit asserted an ESS direction between penalized and free refits on a near-converged fixture — a regime where the mass-conservation projection cancels the penalty's near-proportional push, leaving the comparison at the ~1e-5 nondeterminism noise floor (and the direction premise itself inverts at production scale, per the above). Per the issue's own guidance, no padded tolerance: the threading contract is now pinned via recorded solver options — exactly what the original hardcoded l2_lambda=0.0 bug would have violated — and the behavioral direction lives in the anchor test, in a regime where it's real. Verified stable across repeated runs.

Tests

Full suite: 1,343 passed / 47 skipped on current main; ruff check clean. New: anchor direction contract, explicit-anchor exact-equivalence with presets, validation (labels, shapes, positivity, fail-before-selection), two-stage inherit/override provenance including "design".

🤖 Generated with Claude Code

The l2_lambda penalty divides by a reference weight vector whose choice
decides which way the penalty pulls: under mass conservation its
constrained optimum is w ∝ anchor², so anchoring at heterogeneous
starting weights concentrates rather than spreads. The post-L0 refit
starts from the selection stage's concentrated weights, which made a
refit-stage penalty (the refit_l2_lambda knob shipped in #283) collapse
ESS at production scale (8,408 -> 1,057 at lambda=1e-3 on the 337k-record
US surface) instead of raising it.

- calibrate() gains l2_anchor ("initial" | "uniform"): "uniform" divides
  by the mean starting weight, making the penalty a direct 1/ESS control
  regardless of the starting distribution. An explicit l2_anchor_weights
  vector is the harness seam for anchors the frame cannot express.
- refit_l0_selection/calibrate_l0_refit gain "design": anchor the refit
  at the pre-selection initial weights of surviving records ("stay near
  the survey design"), derived from the selection result. At a fresh
  selection "design" collapses to "initial". refit_l2_anchor follows the
  refit_epochs inherit-or-override pattern; invalid anchors fail before
  the expensive selection stage.
- Direction contract pinned where the effect clears the noise floor by
  orders of magnitude: from heterogeneous starts (ESS 29.3 of 160), the
  initial anchor drives ESS below 0.6x start while uniform drives it
  above 1.4x, at healthy loss.
- Fixes #307: the refit threading test asserted an ESS direction on a
  near-converged fixture where the mass projection cancels the penalty's
  near-proportional push, leaving the comparison at the run-to-run
  nondeterminism noise floor (and the direction itself is anchor- and
  regime-dependent). The threading contract is now pinned via recorded
  solver options — exactly what the original hardcoded l2_lambda=0.0 bug
  would have violated — with the behavioral direction living in the
  anchor test above.

Closes #307.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
MaxGhenis added a commit that referenced this pull request Jul 4, 2026
PR #309 already fixes #307, and does so at the root cause: it replaces the
noisy ESS-direction assertion with the threading contract (recorded solver
options) plus n_nonzero equality, and moves the behavioral direction to a new
anchor test in a regime where it clears the noise floor. #309 further shows the
ESS direction this branch's epsilon fix asserted actually INVERTS at production
scale (an initial-anchored refit penalty lowers ESS on the 337k surface), so a
measured-epsilon margin on the near-uniform fixture would pin a wrong direction.
Restoring test_solve.py to origin/main so this PR is #272-only and does not
conflict with #309 on this file.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@MaxGhenis
MaxGhenis merged commit 08f11cd into main Jul 5, 2026
4 checks passed
@MaxGhenis
MaxGhenis deleted the l2-anchor-semantics branch July 5, 2026 02:43
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.

Flaky: test_refit_l0_selection_threads_l2_lambda_to_refit ESS comparison at 1e-5 margin

2 participants