summaryrefslogtreecommitdiff
path: root/README.md
blob: 155adde5c08dcc7903cdc3e21453ba3ad0d27ad3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
# J-space on nanoGPT

A small-scale replication and critique of Anthropic's **Jacobian Lens**
("J-lens") technique from *"Verbalizable Representations Form a Global
Workspace in Language Models"* (2026,
[transformer-circuits.pub/2026/workspace](https://transformer-circuits.pub/2026/workspace/index.html)).

**Short version of the findings:**

1. The faithful J-lens (rows of `W_U * J_l`, exactly per the paper's Methods)
   has J-lens norms that are strongly anti-correlated with token frequency at
   every layer of a 10.65M-parameter character-level transformer
   (r ≈ -0.61 to -0.69). Anthropic does not control for frequency anywhere in
   their analysis.
2. The correlation is NOT a measurement artifact: it survives the paper's exact
   quantity, verified by a last-layer identity check (cosine similarity 1.0000).
3. The lens is not *only* a frequency meter: two synthetic tokens at identical
   unigram frequency get different faithful J-lens norms when one is predictable
   in context (~1.4-1.5x higher for the structured token, 3 seeds).
4. A causal loss-reweighting test (2x loss weight on 'q' targets vs two
   controls) tests whether effective frequency causally demotes a token's
   J-lens norm. See `results.md` for the latest numbers.

See `docs/blog-jlens-frequency.md` for the write-up and `results.md` for the
numbers. The three independent adversarial reviews that shaped the project
(and caught a real bug in the first implementation) are in `docs/reviews/`.

## What we are NOT claiming

- That Anthropic's J-space doesn't exist. Their headline capacity claim is
  about activation *occupancy* per position, which this repo does not test.
- That the J-lens is useless — it carries genuine conditional-predictability
  signal.
- That toy-model results refute large-model findings. The claim is narrower:
  J-lens *rankings* are frequency-confounded, so a frequency control is
  required before any "privileged subspace" interpretation.

## Repository layout

```
model.py, train.py        nanoGPT (Karpathy) with Maxwell-GPU fixes
src/jlens.py, jlens_v2.py first (buggy) J-lens implementations — superseded
src/jlens_v3.py           FAITHFUL J-lens: rows of W_U * J_l (canonical)
src/synthetic_pair.py     frequency-matched synthetic pair experiment
src/loss_reweight.py      causal loss-reweighting experiment
src/gpt2_jlens.py         GPT-2 scale test (under-powered; see results.md)
tests/                    unit tests (see scripts/test.sh)
scripts/test.sh           canonical test command
docs/blog-jlens-frequency.md  write-up (Feynman-style)
docs/reviews/             three adversarial model reviews
results.md                committed experiment numbers
```

## Reproducing everything

### Environment

- Any Linux box with Docker and an NVIDIA GPU (we used a 4GB Quadro K2200).
- Container image: `pytorch/pytorch:2.4.1-cuda11.8` (last CUDA for Maxwell).
- Sync this repo into the container, e.g. `/workspace/code`.

The K2200 has 4GB VRAM, so batched VJP probes must be chunked (`--chunk 16`);
on a modern GPU you can raise it. Everything runs fp32 (no bf16 on Maxwell).

### 1. Tests

```sh
sh scripts/test.sh
```

Skips gracefully where torch is unavailable.

### 2. Train the base model

Train nanoGPT on `data/shakespeare_char` (10.65M params, 6 layers, d=384,
block 128) and keep the checkpoint at `out-shakespeare-char/ckpt.pt`:

```sh
python3 train.py config/train_shakespeare_char.py
```

### 3. Faithful J-lens, both-ways comparison

```sh
python3 src/jlens_v3.py --checkpoint out-shakespeare-char/ckpt.pt \
    --data_dir data/shakespeare_char --layers 0,1,2,3,4,5
```

Prints per-layer frequency correlations for the faithful lens and the old
proxy, plus the last-layer identity validation. Artifacts land in
`outputs/jlens_v3/`.

### 4. Synthetic frequency-matched pair

```sh
python3 src/synthetic_pair.py --step prep      # builds data/synth_pair
python3 src/synthetic_pair.py --step train --seed 0
python3 src/synthetic_pair.py --step jlens --seed 0
python3 src/synthetic_pair.py --step summary
```

### 5. Loss-reweighting causal test

```sh
python3 src/loss_reweight.py --step train --mode q --seed 0
python3 src/loss_reweight.py --step train --mode control --seed 0
python3 src/loss_reweight.py --step train --mode ctrl_random --seed 0
python3 src/loss_reweight.py --step summary --layers 2,3,4
```

## References

- [Verbalizable Representations Form a Global Workspace in Language Models](https://transformer-circuits.pub/2026/workspace/index.html) — Anthropic, 2026
- [nanoGPT](https://github.com/karpathy/nanoGPT) — Andrej Karpathy