research note  ·  finding 08  ·  confirmed at n=3 seeds — the pre-registered sweep verdict landed 2026-07-10

Fast-weight recall separation at matched budgets, and where the binding actually lives

Sam Larson

pebble, San Francisco

July 9, 2026  ·  updated July 10, 2026 (n=3 sweep verdict)  ·  sam@pebbleml.com

abstract

On high-load associative recall (K = 32 key→value bindings per episode, GPT-2 token entities) at 14M parameters, a fast-weight matrix-state model reads episode-restricted top-1 recall of 0.999 where a param-matched flat-vector ablation reads 0.045 and a FLOP/data-matched transformer reads 0.030 — chance is 0.031. The separation over both baselines exceeds 0.95, more than three times the pre-registered 0.30 win margin. A state-zeroing localization then asks where the binding lives: zeroing the block-0 fast-weight state S₀ alone collapses recall to 0.029; zeroing the block-1 state S₁ changes nothing (Δ = 0.000). Yet no linear tap on either raw state clears the strict recovery threshold — including a tap on S₀ itself. The binding is causally in S₀ but only becomes linearly decodable after the model's own downstream nonlinear processing (pre-LM-head rf@0.9 = 0.674, contender only; the ablation reads 0.0 at the same tap). The pre-registered 27-cell n=3 confirmatory sweep has now landed and CONFIRMS the separation: contender acc_A = [0.9995, 1.0000, 0.9990] across three fresh training seeds; ablation [0.0322, 0.0327, 0.0369]; transformer [0.0271, 0.0293, 0.0286]; paired-seed CIs on both gaps — (0.958, 0.973) vs the ablation, (0.969, 0.974) vs the transformer — exclude the frozen 0.30 win margin. Unpublished.

01Setup

Task 1 of the head-to-head campaign is MQAR-style single-hop recall: bind K = 32 entity key→value pairs (real GPT-2 token IDs), then query one key. The pre-registered load point is K/d_state = 0.5 at d_state = 64. Three arms, matched at 14M-parameter scale:

The metric of record, acc_A, is episode-restricted K-way top-1 accuracy at the query position, read through each arm's own LM head with K-restricted decoding. Chance = 1/32; the demonstration bar is 3× chance. Eval is a pinned query set, n = 4096 queries per cell.

02The separation

recall separation across three matched arms, and the S0-necessity check
fig 1Left: acc_A at K = 32 for the three matched arms — fast-weight contender 0.999, param-matched flat-vector ablation 0.045, FLOP/data-matched transformer 0.030. Dotted line = chance (1/32 = 0.031); dashed line = the pre-registered demonstration bar (3× chance). Right: the S₀-necessity check on the contender — recall with both states intact (0.999), with the block-0 state zeroed (0.029, at chance), and with the block-1 state zeroed (0.999, unchanged). Single seed, n = 4096 queries per cell. Data: round-4 calibration JSONs archived under experiment-runs/2026-07-09_h2h_sweep_launch/round4_inputs/.

Both baselines sit below the demonstration bar; the contender is 0.95+ above both. The pre-registered win margin for this comparison was 0.30. The transformer failure is a within-budget result: at this matched param count, token budget, and training compute, full attention did not learn the task — the claim does not extend to a differently-scaled or differently-trained transformer without its own matched re-run.

02bThe n=3 verdict of record (added July 10)

The margins were frozen to a token file before the first sweep cell launched (pinned 2026-07-09T21:38:00Z, enforced in code per cell). The 27-cell sweep — 3 architectures × 3 tasks × 3 fresh training seeds, identical pinned eval episodes across arms — completed cleanly and was scored under the frozen tiers:

Raw per-cell JSONs, the frozen-margins token, and the exact eval and CI scripts are archived under experiment-runs/2026-07-10_h2h_sweep_harvest/. The campaign's second pre-registered axis — how far this recall carries as context grows while the state stays at 32 KB — has since landed as its own note: constant-memory recall.

03Where the binding lives: the S₀ mechanism

Earlier instrument calibration in this campaign repeatedly failed to decode bindings from the fast-weight state, which looked like a capability problem. The localization experiment shows it was a wrong-layer, wrong-format instrument problem.

Causal necessity. Zeroing S₀ (block 0's cached state) at the end of the bind phase collapses contender recall from 0.999 to 0.029 — chance. Zeroing S₁ (block 1's state, the layer every prior instrument had tapped) leaves recall exactly unchanged. All of the causally necessary binding information lives in S₀.

Linear legibility. A closed-form ridge tap (24,576 fit points, 4,096 held-out) at four placements:

rf@tau for four tap placements on the contender
fig 2Recovered fraction rf@τ (ridge-decoded vector clears cosine τ against the true target) for four tap placements on the contender. The three taps on raw recurrent state — including the tap directly on S₀, the state the zeroing proves is causally necessary — recover essentially nothing at any threshold. Only the post-block-1, pre-LM-head hidden state is linearly decodable (rf@0.9 = 0.674). On the ablation arm, the same pre-LM-head tap reads 0.0 at every threshold. Single seed. Data: experiment-runs/2026-07-09_h2h_tap_localization/results/.
key observation The binding is causally stored in S₀ in a format no linear (state, query) read can extract; it becomes linearly legible only after block 1's own nonlinear forward pass has processed the S₀-derived signal. Probing the "obvious" state location — or assuming linear decodability of a causally necessary representation — both fail here.

04Caveats — read before citing

05Reproducibility

Raw result JSONs and manifests are archived in the project repository under experiment-runs/2026-07-09_h2h_tap_localization/ (tap and zeroing legs), experiment-runs/2026-07-09_h2h_sweep_launch/round4_inputs/ (the three calibration cells; SSD archive), and experiment-runs/2026-07-10_h2h_sweep_harvest/ (the 27 sweep training JSONs, the 18 verdict-grade eval JSONs, the frozen-margins token, md5 manifests, and the exact eval + CI scripts). The figure-generation script for this page is at assets/plots/generate_fast_weight_recall.py.