← all analysis · · docs/analysis/2026-05-22-dual-readout-week2.md
Dual Readout — NLA + SAE on Gemma-3-12B-IT L32 (Path A Week 2)
On this page
Date: 2026-05-22
Status: Complete — Path A Week 2 deliverable. Per-token dual readout
(NLA verbalization + top-K GemmaScope 2 SAE features) ran on the barrier-knockin
prompt triple against Gemma-3-12B-IT at L32. 47 tokens × 2 readouts.
Predecessors: Week 1 (2026-05-nla-sidecar.md) gave a final-token-only NLA
readout. This week adds (a) the second, independent SAE leg and (b) per-token
resolution at every input position, not just the last.
Companion artefacts:
- /analysis/2026-05-first-attribution-graph/ — Phase B Gemma-2-2B attribution graph used for cross-generation feature-cluster sanity check.
mechinterp/outputs/dual_readout_v1/— per-prompt JSON outputs and source parquet.
This document covers the Week 2 plan steps in
docs/superpowers/plans/2026-05-track-b-path-a-six-week-execution.md. Week 4’s
formalized cross-validation rules are deferred to that plan; this artefact
contributes the empirical observations Week 4 will codify against.
1. What the dual readout is
Two independent interpretability methods read the same residual-stream activation at the same site (Gemma-3-12B-IT, layer 32, every token position):
| NLA (Anthropic 2026) | GemmaScope 2 SAE (DeepMind 2026) | |
|---|---|---|
| Output | A natural-language paragraph describing what the activation encodes | A sparse vector of feature activations; we keep the top-K=10 by magnitude |
| Decomposition | Holistic — one sentence about the whole activation | Discrete — feature IDs with scalar activations |
| Validation | The actor is trained so that a critic can reconstruct the original activation from the text (RL reward = MSE) | Reconstruction RMSE / explained variance against the original residual stream |
| Pipeline file | mechinterp/scripts/nla_inference.py (vendored) + SGLang AV server | mechinterp/scripts/04_dual_readout.py (JumpReLUSAE, direct HF download) |
Both read the same activation site; both can be wrong; the question is do they fail in the same way? When both name “below-barrier → loss of principal”, that is a stronger claim than either method making it alone. When one is silent and the other speaks, that signals an audit point. When they disagree, that is a falsification opportunity.
2. SAE choice (deviation from plan)
The Week 2 plan defaulted to GemmaScope 2 64k width, medium L0 (30-60). The
actual HuggingFace tree at google/gemma-scope-2-12b-it does not have this
combination at L32:
| Location | Layers covered | Widths | L0 labels (raw l0 values) |
|---|---|---|---|
resid_post/ | 12, 24, 31, 41 (≈25%/50%/65%/85% depth) | 16k, 65k, 262k, 1m | small (~20), medium (~40-60), big (~120) |
resid_post_all/ | all 48 layers, incl. L32 | 16k, 262k only | small (~20), big (~120) only |
The plan’s choice exists at the 4 curated layers but not at L32. The closest
options at L32 in resid_post_all/ are:
layer_32_width_16k_l0_big(l0=120) ← chosenlayer_32_width_16k_l0_small(l0=20)layer_32_width_262k_l0_big(l0=120)layer_32_width_262k_l0_small(l0=20)
Rationale:
- Width 16k matches the Phase B Gemma-2-2B SAEs (
mwhanna/gemma-scope-transcoders, 16k), so the dictionary granularity comparison is apples-to-apples. - L0 = 120 (“big”) gives ample headroom above K=10 for top-K extraction. The “small” variant (l0=20) is too sparse to robustly rank top-10 active features per token.
- L32 was fixed by the released NLA checkpoint (
kitft/nla-gemma3-12b-L32-av/ar). Picking a different layer to satisfy the plan’s SAE preferences would have broken NLA/SAE alignment — worse than this deviation.
The mismatch (l0=120 vs. plan-target 30-60) inflates the measured L0 on SP-domain prompts (see §3.1), but does not invalidate top-K analysis at K=10.
3. Run record
3.1 Pipeline
-
05_capture_per_token_activations.py— load Gemma-3-12B-IT bf16 on cuda, forward on each prompt withoutput_hidden_states=True, takehidden_states[32]at every token position. Persist 47 rows (19 + 19 + 9 tokens × 3 prompts) tomechinterp/outputs/dual_readout_v1/per_token_l32_activations.parquet. Final-token activation norms are byte-identical to Week 1 (79 793 / 80 295 / 65 979). -
04_dual_readout.py --device cpu --nla-actor <AV path>—- Download
google/gemma-scope-2-12b-it/resid_post_all/layer_32_width_16k_l0_big/{params,config}from HF. - Instantiate a minimal
JumpReLUSAE(see §3.2). Encode all 47 activations. - Take top-K=10 by activation magnitude per row.
- For each row, POST the activation to a running SGLang server (
kitft/nla-gemma3-12b-L32-avactor, Triton attention backend,--disable-radix-cache) and capture the<explanation>text. - Join SAE features + NLA explanation per token into one JSON per prompt.
- Download
-
SGLang memory budget. At
--mem-fraction-static 0.85SGLang reserves ~103 GB of the 121 GB unified memory. The SAE encode (16k × 3840 ≈ 500 MB in fp32) wouldn’t seem to need that much headroom butsafetensors.load_fileon cuda OOMed; falling back to--device cpufor the SAE worked first try. The SAE encode runs in milliseconds on CPU for 47 rows — no penalty.
3.2 SAE forward pass (JumpReLU)
pre = (x - b_dec) @ W_enc + b_enc # [..., d_sae]
features = pre * (pre > threshold).float()
recon = features @ W_dec + b_dec
Lowercase param keys on disk (GemmaScope 2 convention): w_enc, w_dec,
b_enc, b_dec, threshold. GemmaScope 1 used uppercase; the
JumpReLUSAE constructor accepts both.
3.3 Reconstruction sanity check
On the 47-row batch:
| Metric | Value | Reading |
|---|---|---|
| Mean ‖x‖ (activation L2 norm) | 108 404 | Expected for L32 of Gemma-3-12B (NLA was trained for ‖x‖≈80 000 in-distribution; SP-domain activations are slightly higher but in-band) |
| RMSE(recon − x) | 1 278 | RMSE / ‖x‖ ≈ 1.2% — clean reconstruction |
| Explained variance | 0.828 | Good for an SAE; well above the chance baseline |
| Mean L0 (active features per token) | 567 | 4-5× the trained L0=120. OOD inflation on SP-domain prompts, not a math bug (reconstruction quality rules out a bad forward pass). |
The L0 inflation is itself a finding: on prompts the SAE was not trained for (financial structured products), the same activation vector requires many more dictionary entries to reconstruct. This does not invalidate the top-K=10 extraction — it just means top-10 is a smaller fraction of the total than it would be in-distribution.
4. Cross-method comparison — per token
Three behavioural regimes emerge from reading the 47 tokens side-by-side.
4.1 Regime 1 — early positions (0-4): both methods independently say “no finance content yet”
| Position | Token | NLA verbalization (first sentence) | SAE top-3 |
|---|---|---|---|
| 0 | <bos> | ”Fragmented, incoherent academic text with garbled phrasing…” | #180 (91 070), #109 (72 008), #178 (56 156) |
| 1 | In (or A) | “Technical article structure: educational blog format… eigenvalues / Fibonacci sequence / Gibbs energy” | #205 (41 583), #221 (26 463), #113 (26 447) |
| 2 | a | ”Article structure… news summary or tutorial snippet introducing a programming topic” | #15019, #349, #313 |
| 3 | barrier | ”Academic/chemical database entry format… research paper about a specific chemical topic” | #15019, #15663, #313 |
| 4 | reverse | ”Technical semiconductor paper context… avalanche diodes and BJT parameters” | #15019, #15663, #313 |
Both methods agree these positions are not finance-content-loaded:
- NLA decodes thematically unrelated concepts (chemistry, electronics, math) — the residual stream has too little context for the actor to project into a coherent finance verbalization. Matches the
nla_inference.pycaveat: “Early-sequence positions (first ~10 tokens): layer-K has seen few tokens, residual stream hasn’t accumulated signal. Decodes trend toward training prior.” - SAE activates position-specific features at
and position 1 (#180/#109/#178 for BOS; #205/#221/#113 for “In”/“A”) that do not appear at any later position. These are residual-stream “boundary” markers, not domain content.
This is a clean cross-method agreement on a negative finding: “the model has not yet committed to a finance reading at these positions.”
4.2 Regime 2 — domain onset (positions 5+): both methods independently identify financial context
Starting at position 5 ( convertible), every NLA verbalization across all three prompts opens with “Financial…” — investment context, glossary format, derivatives Q&A, structured product description. The SAE’s dominant feature trio also stabilizes: #15019 / #15663 / #313 appear in the top-3 at virtually every position from 5 onward.
This is cross-method agreement on a positive finding: by position 5, the
model has recognized the structured-product context. The interpretation
candidates for feature #15019 (top-1 at almost every finance position):
- A structured-product / financial-derivative concept feature.
- Or — given how broadly it fires — a finance-text meta-feature (genre marker).
This is a candidate for the GemmaScope auto-interp lookup
(TODO: feat=#15019 via Neuronpedia).
4.3 Regime 3 — directional positions (10-15): asymmetric, only partly directional
The contrast positions for the barrier conditional are closes/stays (pos 10), below/above (pos 11), and the barrier at maturity (pos 12-15).
| Position | Prompt 1 (below) NLA · top-2 SAE | Prompt 2 (above) NLA · top-2 SAE |
|---|---|---|
| 10 | ”barrier pricing… synthetic long/short” · #15019 #313 | ”barrier option… conditional rule” · #15019 #313 |
| 11 | ”options/barrier strategy… callable convertible … if the price falls below” · #15019 #15663 | ”barrier/knock-out option … if the underlying stays above” · #15019 #20 |
| 12 | ”European knock-out barrier … underlying asset is above” · #15019 #416 | ”structured note is protected against do[wnside]” · #15019 #416 |
| 13 | ”FX options/structured products … scenario about barrier breach” · #15019 #15663 | ”knock-out barrier condition … as long as the underlying stays” · #15019 #15663 |
15 ( maturity) | “European option payoff at maturity … bond is above” · #15019 #15663 | ”quantitative payoff analysis … at maturity or at maturity” · #15019 #15663 |
Observations:
- SAE features diverge at pos 11.
#15663appears in prompt 1’s top-3 atbelow;#20appears in prompt 2’s top-3 atabove. This is the cleanest single-position SAE divergence between the two conditionals. - NLA explicitly mentions directional language only on prompt 2 (above). The above-barrier verbalization at pos 12 says the structured note is “protected against downside” — a domain-correct reading. The below-barrier verbalization at pos 12 says “underlying asset is above” — the wrong direction. Confabulation confirmed: the NLA produced an “above” claim at a “below” position. The cross-check against the prompt text (
belowat pos 11) flags this as a candidate hallucination, not a finding. - Convergence on barrier-event language, not on the payoff direction. Both prompts trigger NLA mentions of “barrier breach”, “knock-out”, “knock-in” — but neither verbalization at the directional positions makes the payoff claim (“the investor loses principal” / “the investor receives par”). The payoff claim only surfaces at the final-token position (§4.4).
4.4 Regime 4 — final-token (pos 18 investor): payoff direction at last
| Prompt | NLA verbalization (excerpt) | SAE top-3 |
|---|---|---|
| 1 (below) | “definition/explanation of structured products … the outcome for the investor when the index falls below the barrier, specifically the loss of principal or return” | #15019, #608, #313 |
| 2 (above) | “explaining a structured product … the investor receives the principal plus a small return or loses the principal in the ETF/bond hybrid” | #15019, #608, #313 |
| 3 (neutral) | “structured definition of a structured product … An Enhanced Yield Note is a structured product” | #15019, #15663, #313 |
These are byte-identical to the Week 1 sidecar (§3 of
2026-05-nla-sidecar.md) — confirms the run is deterministic (temp 0)
and reproducible across sessions.
The SAE top-3 at the final position is near-identical between prompts 1 and 2 (#15019, #608, #313 at both, with #601/#416 close behind). Same dominant structured-product context features. The difference between “below → loss” and “above → equivocal” is not visible at the SAE top-3 level — it lives either lower in the SAE feature rank, or in the combined activation pattern the NLA verbalizes but discrete top-K features do not surface.
5. Feature-cluster sanity check vs. Phase B (Gemma-2-2B)
The Phase B attribution graph (2026-05-first-attribution-graph.md §3)
reported, on Gemma-2-2B with mwhanna/gemma-scope-transcoders:
- Strongest individual feature for the
loseslogit:L2 pos11(' below') feat=2916 at 0.140. - 98 features at concept-of-interest positions cleared |attribution| > 0.05.
On Gemma-3-12B-IT with GemmaScope 2 at the same prompt and same input position
(pos 11 below):
- Top SAE feature IDs (16k):
#15019,#15663,#313,#20,#14291. - Direct ID match with
feat=2916is not expected — different model generation, different SAE training corpus, different dictionary initialization. The IDs are not portable across releases. - Conceptual neighbourhood is consistent: multiple SAE features fire at
the barrier/below position, the dominant structured-product feature
(
#15019) is among them, and a position-specific feature (#15663for below,#20for above) discriminates the two directional prompts.
This satisfies Week 2 step 4 (“sanity-check that SAE features at known concept positions are consistent with Phase B findings qualitatively”).
6. Proto-rules — Week 4 input
Week 4 will formalize four cross-validation rules. Week 2’s data already populates each cell of the working frame in the Path A plan:
| Working-frame pattern | Concrete Week 2 example |
|---|---|
| NLA + SAE agree (high confidence) | Positions 5-18 every prompt: both methods independently identify “structured-product / financial-derivative” content. Feature #15019 co-occurs with NLA “financial/investment” framing. |
| NLA only (hypothesis, not confirmed) | Final-token ’ investor’ on prompt 1: NLA names “loss of principal”; the SAE top-3 at the same position is dominated by domain-context features (#15019, #608, #313) that do not visibly discriminate below from above. The directional claim is suggestive but not corroborated by the top-K SAE leg. |
| SAE only (unverbalized, possible blind spot) | Position 11 SAE divergence: feature #15663 distinguishes below from above (#20). The NLA verbalization at those positions does not call out a direction-specific feature. The SAE sees a discriminating signal the actor’s English does not surface. |
| NLA contradicted by context (confabulation candidate) | Position 12 of prompt 1: NLA says “underlying asset is above” when the actual preceding token is below. The cross-check is against the prompt text, not against the SAE — but the rule fires the same way. |
7. Caveats
- Same model/generation/scale confound as Week 1. Phase B used Gemma-2-2B with GemmaScope 1; Week 2 uses Gemma-3-12B-IT with GemmaScope 2. Cross-method comparisons here are within-Week-2 (NLA vs. SAE on the same activation); cross-week comparisons are conceptual, not numeric.
- Three prompts. This is the same prompt triple as Phase B and Week 1. No claim is made about NLA-SAE agreement across the SP domain in general; this is a proof-of-protocol artefact, not a population study.
- SAE deviation. The Week 2 plan’s “64k / medium L0” SAE is not available at L32. Width 16k / l0_big is the closest match. The l0=120 trained sparsity with measured 567 active features per token on SP-domain prompts (4-5× inflation) is itself a finding; top-K=10 analysis is unaffected.
- NLA confabulation, again. Each prompt’s verbalization mis-names the product (“equity linked note”, “Enhanced Yield Note”, “ETF/bond hybrid”, “callable convertible bond”, “credit/equity hybrid instrument”, “knock-out bond”) — the prompt explicitly says barrier reverse convertible. Same caveat as Week 1; the cross-validation rule for NLA-only claims downgrades them to hypotheses.
- Inference-only. No NLA or SAE training was done in this work. The contribution is prompt selection, dual-readout orchestration, and the cross-method comparison framework.
8. FINMA 08/2024 §VI implications
This artefact directly addresses FINMA’s third assessment leg (“plausibility / robustness of results”). The Week 1 sidecar made the case for method triangulation in principle. Week 2 demonstrates the operational form: two methods, same site, per-token resolution, and concrete categories (agree / NLA-only / SAE-only / contradicted) that map to confidence claims.
What this artefact does not yet do:
- Map proto-rules → FINMA Randziffer. That is Week 4.
- Run on the SP-Benchmark questionnaire (25 × 7). That is Week 3.
- Make a regulator-grade claim. The 47-token, 3-prompt evidence is a methodology demonstration, not a sign-off.
9. Status
- Per-token L32 activation capture (47 rows, all 3 prompts)
- GemmaScope 2 SAE at L32, 16k width, l0_big — loaded, RMSE/EV validated
- Per-token NLA verbalization via SGLang AV (deterministic, byte-identical to Week 1 at the final position)
- Dual-readout JSON outputs (
prompt{1_below,2_above,3_neutral}.json) - Feature-cluster sanity check vs. Phase B (qualitative)
- Proto-rules populated from observations (§6)
- Auto-interp lookup of dominant features (#15019, #15663, #313) via Neuronpedia — separate TODO
- Week 3: SP-Benchmark 25 × 7 dual-readout run
- Week 4: formal cross-validation rules + FINMA Randziffer mapping