Skip to content

Seed the calibration weight dropout so builds are reproducible - #507

Draft
MaxGhenis wants to merge 4 commits into
mainfrom
deterministic-calibration
Draft

MaxGhenis wants to merge 4 commits into
mainfrom
deterministic-calibration

Conversation

@MaxGhenis

@MaxGhenis MaxGhenis commented Oct 1, 2026 •

Copy link
Copy Markdown
Contributor

WIP — impact pending four hub-controlled builds. This PR remains a draft.

Two builds with the same calibration inputs could produce different household weights because the dropout masks used torch's unseeded global generator. Every Budget comparison between dataset builds inherited that noise.

The historical claim is verified from four saved aggregate summaries of main b45c373: in 2026, income tax ranged from £312.411684864bn to £313.196281856bn (spread £0.784596992bn), and household net income ranged from £1,756.085878784bn to £1,759.036964864bn (spread £2.951086080bn). The summaries used the same policyengine-uk head 44240bd8. These confirm the rounded £0.8bn/£3bn claim; they are historical evidence, not results for the updated branch. jobs/adopt-ud507/verify_historical_spread.py verifies the saved summaries without rebuilding or running a simulation.

Calibration randomness now uses one documented default, DEFAULT_CALIBRATION_SEED = 0 in policyengine_uk_data/utils/calibrate.py:19:

  • Dense local-area dropout uses a fresh torch.Generator().manual_seed(seed) at utils/calibrate.py:397 and passes it to the sole random draw at :404. Weight-prior initialization is deterministic; there is no other sampling in that module or the constituency/local-authority calibration wrappers. Both production calls in datasets/create_datasets.py:269 and :296 use this shared default.
  • The currently inactive L0 backend uses the same default at utils/calibrate_l0.py:167. Its library draws initialization jitter and HardConcrete gates internally; the model constructor and fitting run inside torch.random.fork_rng(devices=[]), seeded at :253, with the caller's CPU RNG state restored afterward.

The tiny-fixture tests compare saved weight bytes, perturb ambient torch state, check that calibration leaves the caller's RNG stream unchanged, and check that different seeds change weights. Dense calibration also compares two fresh processes with the parent. Reproducibility requires fixed inputs, frozen targets, dependency versions, torch thread count and platform. Upstream geography preprocessing keeps its separate existing seed; this PR does not change imputation or target-download behavior.

The saved merge of current main 2b9c1c2c64ce was resumed without conflicts. uv.lock remains policyengine-uk 2.122.2 / core 3.32.13.

Build plan: jobs/adopt-ud507/BUILD_PLAN.md, with exact setup/build/comparison commands and a proposed four-build queue entry. The shared setup harness normally cherry-picks this PR's seed patch onto every build; a pinned wrapper omits that step so branch builds use their existing patch and main controls retain unseeded dropout. All four runs use the same frozen targets/models, locked environment, 512 epochs and one thread. Comparison checks weight bytes and reports income-tax and household-net-income spread. No dataset builds or microsimulations were started by this job.

Hub filesystem state is outside this job's writable sandbox. The build plan, proposed queue row and progress record are prepared in the workspace; the hub must install them under ~/reviews/uk-hub/jobs/adopt-ud507/ and append the row before giving GO. Build impact is pending that hand-off and the four runs.

Validation: 33 focused tests passed, covering dense and L0 seed behavior, fresh processes, weight saving/loading, validation targets and calibration progress. Latest uvx ruff format --check ., targeted Ruff lint (E4,E7,E9,F), script syntax checks and git diff --check passed. Independent GPT-6.1 Sol review APPROVED exact final head 60a87ff7ca8e75abea0f09bb49d37fd92901fc39 with no important defects found, including the calibration code and controlled build plan. Subfleet's requested --task review --tier hard dispatch was blocked by its inbox being outside the writable sandbox; the independent review used the available Sol agent instead. CI is queued.

axiom: n/a: data build infrastructure (calibration RNG).

calibrate_local_areas replaced 5% of the log-weights with their mean each
epoch, choosing them with torch.rand_like. That draws from torch's global
generator, which torch seeds differently in every process and nothing in
the build seeded, so two builds of the same commit with the same inputs gave
different household weights. The dropout now has its own torch.Generator,
seeded from a new seed argument (default 0), and leaves the global
generator alone.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
MaxGhenis and others added 3 commits October 11, 2026 21:49
Brings in the 95 commits on main since this branch forked, including the 10/8 release batch (d833) and its relock to policyengine-uk 2.122.2 (from 2.93.0). No conflicts.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@MaxGhenis

Copy link
Copy Markdown
Contributor Author

WIP hand-off to the UK hub at 60a87ff. Code and focused tests are complete; impact is pending the four controlled builds. Keep this PR a draft.

  • Resumed and pushed the saved main merge d9d13a18; current main 2b9c1c2c64ce merged without conflicts. Lock remains policyengine-uk 2.122.2/core 3.32.13.
  • Dense dropout and the inactive L0 backend use the documented calibration seed 0. Equal seeds reproduce saved weight bytes; different seeds change them; caller CPU RNG state is preserved.
  • 33 focused tests passed, plus latest Ruff formatting, targeted lint, script syntax and diff checks. CI is queued; superseded runs have finished.
  • Historical 2026 spreads verified from saved aggregate summaries: income tax £0.784596992bn, household net income £2.951086080bn, confirming the rounded £0.8bn/£3bn claim. These are separate from the pending controlled experiment.
  • Independent GPT-6.1 Sol APPROVED this exact head, with no important defects found in code, tests or the runbook. The requested Subfleet review command failed before dispatch because its inbox is outside the writable sandbox; the independent Sol collaboration agent performed the review instead.

The committed build plan supplies exact setup, four-build and comparison commands. It adapts the pinned required hub harness to omit its automatic seed cherry-pick, retaining unseeded main controls. Inputs, targets/models, locks, one thread, 512 epochs and one OA clone are fixed, and comparison requires identical branch weight bytes and differing main weights before reporting aggregate spreads.

The sandbox prevents writes to ~/reviews/uk-hub. The actual queue is not yet updated. The hub must install the committed artifacts under ~/reviews/uk-hub/jobs/adopt-ud507/ using the runbook's installation commands, append the single row from QUEUE_ROW.md with the next row number, and append the prepared workspace jobs/adopt-ud507/HANDOFF.jsonl record to its handoffs file. The driver requires the hub's explicit GO before launch.

No dataset builds or microsimulations were started by this job. No merge requested; impact must be measured through the queue before this leaves draft.

This branch has not been deployed

No deployments
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.

1 participant