Skip to content

(WIP) Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast#509

Closed
eugenevinitsky wants to merge 2 commits into
3.0from
ev/dropout-invariant-obs
Closed

(WIP) Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast#509
eugenevinitsky wants to merge 2 commits into
3.0from
ev/dropout-invariant-obs

Conversation

@eugenevinitsky

@eugenevinitsky eugenevinitsky commented Jul 5, 2026

Copy link
Copy Markdown

What

Three related changes with one theme — observation geometry is the policy's interface and must be identical between training and eval envs:

  1. Dropout-invariant layout: road dropout (env noise) no longer changes the obs vector size. The layout is always the full obs_slots_* counts; dropout only limits how many slots carry data, zero-padded with the existing valid-count features reporting what was kept. Content selection and its RNG path unchanged; at p=0 bit-identical.
  2. Eval sections inherit obs geometry: [eval.validation_defaults] pinned obs_slots_lane_n/boundary_n = 80 and [eval.behaviors_defaults] pinned obs_slots_partners_n = 32. Any training config with different geometry produced eval observations the policy could not unpack. Those pins are removed; eval envs take geometry from the training config.
  3. Fail fast: the policy records the obs length it was built for (expected_obs_dim), and EvalManager._run_inline raises with an actionable message on mismatch — instead of an asynchronous CUDA gather assert ~2h into training that poisons the context and kills the job after the manager already printed "continuing".

Why

Both the 2026-07-04 and 2026-07-05 nightly multi runs (trained at 60/40 slots with dropout 0.2/0.3) died at their first inline eval with ScatterGatherKernel device asserts. Night 1 was the dropout-shrunken layout meeting the clean macro; night 2 — after pinning eval dropout — was the section's hard 80/80 slot pins. Same disease: eval env obs shape ≠ policy obs shape. This PR removes both causes and makes any future instance a one-line error at eval start.

Notes

  • Compat: checkpoints trained with dropout > 0 under the old layout won't load against the new one (only the two crashed nightly batches exist in that regime). Dropout-free checkpoints unaffected; smoke goldens should not move.
  • Verified: full C test suite; 74 unit tests incl. 3 new (obs space invariant to dropout; valid counts/padding; the exact regression — dropout-trained policy on clean-env obs); CPU training run with dropout whose shutdown clean-eval passes. Eval-vs-train num_obs equality for the nightly config verified against the merged eval args (691 == 691).
  • The cluster working tree currently carries the equivalent config edits as a stopgap; they come out when this merges.
  • The explicit env.obs_dropout_* = 0.0 in validation_defaults stays — zeroing noise at eval is semantics, not geometry, and is safe after (1).

🤖 Generated with Claude Code

Road dropout is env noise: it limits how many lane/boundary slots carry
data each step, but it must not change the observation interface. The
obs vector is now always laid out for the full slot counts, with unused
slots zeroed and valid-count features reporting what was kept; the
subsample-to-kept content logic is unchanged. Sizing, the backbone
slicing, the obs-overlay renderer, and the C layout tests follow.

Previously the layout was sized by the post-dropout kept counts, so two
envs differing only in dropout had incompatible obs spaces. The inline
clean eval (which zeroes dropout) fed a dropout-trained policy longer
obs than it was built for, crashing the nightly multi runs with a CUDA
gather assert at their first eval.

Checkpoints trained with dropout > 0 under the old layout do not load
against the new one; dropout-free checkpoints are unaffected (at
dropout 0 the layout and fill path are identical).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@eugenevinitsky eugenevinitsky changed the title Make obs layout invariant to road dropout (WIP) Make obs layout invariant to road dropout Jul 5, 2026
[eval.validation_defaults] pinned obs_slots_lane_n/boundary_n = 80 and
[eval.behaviors_defaults] pinned obs_slots_partners_n = 32, so any
training config with different obs geometry built an eval env whose
observations could not be unpacked by the trained policy — the same
crash class as the dropout-layout bug, and what actually killed the
2026-07-05 nightly multis after the dropout pin was in place. Obs
geometry is the policy interface: eval sections now inherit it from the
training env.

The policy records the obs length it was built for, and _run_inline
raises with a clear message when an evaluator env disagrees, instead of
dying ~2h later on an asynchronous CUDA gather assert that poisons the
context.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@eugenevinitsky eugenevinitsky changed the title (WIP) Make obs layout invariant to road dropout Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast Jul 5, 2026
@eugenevinitsky eugenevinitsky changed the title Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast (WIP) Obs geometry is the policy interface: dropout-invariant layout, eval inheritance, fail-fast Jul 6, 2026
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