Skip to content

Change beta0_ridge to standard ridge on β0 magnitude#238

Closed
jaredgalloway wants to merge 1 commit into
mainfrom
237-beta0-ridge-magnitude
Closed

Change beta0_ridge to standard ridge on β0 magnitude#238
jaredgalloway wants to merge 1 commit into
mainfrom
237-beta0-ridge-magnitude

Conversation

@jaredgalloway

@jaredgalloway jaredgalloway commented Apr 22, 2026

Copy link
Copy Markdown
Member

Summary

  • Rewrite _beta_ridge_penalty as a standard ridge: sum β0**2 across all conditions (reference included) times beta0_ridge. The old form penalized non-reference β0 difference from the reference — asymmetric under relabeling, and left the reference unanchored.
  • Extract _beta_ridge_penalty to a module-level function so it's unit-testable directly (was a closure inside fit).
  • Add three new correctness tests: gradient matches 2 * r * β0[d] for every d; penalty is invariant under condition relabeling; penalty is 0 iff every β0 is 0, with the formula checked against the model-under-test.
  • Rewrite test_beta0_ridge_penalty — the old assertion (differences shrink) was literally the old invariant, so it had to change.
  • Fix tuple(fit_config["beta_clip_range"]) crash when YAML sets beta_clip_range: null. Shared fix across three experiment helpers (scv2-spike, simulation, loss-normalization): a _clip_range helper returns None untouched, tuple-wraps otherwise.
  • Update production spike config (config.yaml): tol 1e-4 → 1e-5, maxiter 50 → 75 (top-level + ge_kwargs + cal_kwargs); l2reg 0 → 1e-7; beta0_ridge 0 → 1e-3 (new semantics); beta_clip_range [-10, 10] → null (disables clipping, replaced by smooth regularization on the intercept).
  • Reset beta0_ridge in config_experimental.yaml and config_test.yaml to 0.0 — the existing 1e-4 values were calibrated for the old difference-from-reference semantics and are not directly transferable.
  • Update CLAUDE.md with the new beta0_ridge semantics and the correct YAML encoding for disabling beta_clip_range (single null, not [null, null]).

Test plan

  • pixi run lint — clean
  • pixi run fmt-check — clean
  • pixi run test (pytest --doctest-modules) — 185 passed, including 4 new correctness tests
  • Snakemake dry-run on updated production config.yaml — DAG constructs cleanly with beta_clip_range: null
  • Production scv2-spike pipeline executed on orca04 — 5/5 rules complete in ~30 min, no errors, no TypeError from clip handling

Production run results

Executed pixi run remote-pipeline -- spike prod host=orca04. Pipeline completed cleanly; results preserved under experiments/scv2-spike/results-prod-237-beta0-ridge-magnitude/ in the main clone (gitignored per repo convention, matching how results-prod-232-* and results-prod-235-* are handled).

Training loss at fusionreg=0.0, rep_1 (first row of cross_validation_loss.csv):

Run loss
#237 (this PR) 0.6147
#232 l2reg-1e-7 (closest baseline) 0.6192
#232 tight-tol 0.5968
#235 times-seen-threshold 0.6166

The new run lands squarely within the baseline range — a touch lower than the most directly comparable baseline (#232 l2reg-1e-7), consistent with tighter tol=1e-5 and longer maxiter=75 producing slightly better convergence. All per-condition losses finite, CV completed across the full fusionreg grid.

Closes #237

🤖 Generated with Claude Code

Replace `_beta_ridge_penalty` with a standard ridge on β0 — summing β0**2
across all conditions (reference included). Previously the penalty was on
the squared difference between each non-reference β0 and the reference,
which was asymmetric and left the reference unanchored.

Extract `_beta_ridge_penalty` to a module-level function so it can be
unit-tested directly. The closure inside `fit()` no longer duplicates it.

Add three new correctness tests:

  - gradient check: grad = 2 * r * β0[d] for every d
  - label-permutation invariance: penalty unchanged when conditions relabel
  - zero-at-origin: penalty is 0 iff all β0 are 0, with explicit formula

Rewrite `test_beta0_ridge_penalty` to check magnitude shrinkage across
all conditions (old semantics checked differences, which was the old
invariant, not the new one).

Fix `tuple(fit_config["beta_clip_range"])` crash when YAML value is
`null` — affects all three experiment helpers (scv2-spike, simulation,
loss-normalization). Introduce a shared `_clip_range` helper that
returns `None` untouched and otherwise tuple-wraps.

Update production spike config (config.yaml):

  - tol:  1e-4 → 1e-5 (top-level, ge_kwargs, cal_kwargs)
  - maxiter: 50 → 75 (top-level, ge_kwargs, cal_kwargs)
  - l2reg: 0.0 → 1e-7
  - beta0_ridge: 0.0 → 1e-3 (new semantics)
  - beta_clip_range: [-10, 10] → null (clipping disabled)

Reset `beta0_ridge` in config_experimental.yaml and config_test.yaml to
0.0 — the old 1e-4 values were calibrated for the difference-from-
reference penalty and are not directly transferable.

Update CLAUDE.md with notes on the new beta0_ridge semantics and the
correct YAML encoding for disabling beta_clip_range.

Closes #237

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@jaredgalloway

Copy link
Copy Markdown
Member Author

Closing without merging — failed experiment. Keeping the branch (237-beta0-ridge-magnitude) and the linked issue around for reference.

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.

Change beta0_ridge to a standard ridge on β0 magnitude

1 participant