| --- |
| license: mit |
| tags: |
| - latent-reasoning |
| - chain-of-thought |
| - coconut |
| - curriculum-learning |
| --- |
| |
| # lyot-chain10 β Coconut latent reasoning on a depth-10 chain |
|
|
| Four GPT-2-style checkpoints (2 layers, 15.0M params, 40-token symbolic vocabulary) trained |
| with [Coconut](https://github.com/facebookresearch/coconut)-style continuous chain-of-thought |
| on a graph-reachability task requiring **ten sequential latent steps**. |
|
|
| Part of *Learn Your Own Thoughts* (ATC). Coconut's previous ceiling in our experiments was |
| depth 4 under a fixed clock schedule; these reach **eval accuracy 0.999** at depth 10. |
|
|
| ## Task |
|
|
| Which of two candidate nodes is reachable from the root? |
|
|
| ``` |
| <eos> 3 17 | 8 1 | 15 16 | ... | 5 7 [Q] 19 13 [R] 20 [A] -> 19 |
| \___ edges ___/ \cands/ \root/ |
| ``` |
|
|
| A depth-10 chain plus an **isomorphic unreachable twin** β 22 nodes, 20 edges, 77 tokens. The |
| distractor is the target's counterpart in the twin component, matching depth and in/out-degree, |
| so no local feature separates the candidates. Chance is 0.500. Node ids are permuted per task, |
| which removes an id-ordering shortcut worth ~0.30 accuracy. |
|
|
| ## Checkpoints |
|
|
| Each is a full training state: `model`, `optimizer`, `epoch`, `stage`, `metrics`. |
|
|
| | file | uniform_prob | shuffle_nodes | epoch | eval/acc | |
| |---|---|---|---|---| |
| | `...ucou7ar1-ep157-s10-eval0.999.pt` | 0.5 | true | 157 | **0.999** | |
| | `...bjmzm8ql-ep139-s10-eval0.998.pt` | 0.1 | false | 139 | **0.998** | |
| | `...pclc3j4q-ep116-s10-eval0.998.pt` | 0.5 | false | 116 | **0.998** | |
| | `...6oth0ni8-ep162-s10-eval0.964.pt` | 0.1 | true | 162 | 0.964 | |
|
|
| `eval/acc` is on 1000 held-out graphs at full difficulty and full latent budget. The filename |
| embeds the wandb run id (project `lyot-chain10`). All four were at curriculum stage 10 when |
| saved. The best is `shuffle_nodes=true`, the shortcut-free setting. |
|
|
| ### The clock baseline (`c10clk-*`), at chance |
| |
| The four `c10clk-*` files are the control, and they are **chance-level by design, not |
| broken**. Everything about them matches the arms above except that the curriculum advances |
| on upstream's fixed schedule (`epochs_per_stage: 5`) rather than on measured accuracy: |
|
|
| | file | uniform_prob | shuffle_nodes | epoch | eval/acc | |
| |---|---|---|---|---| |
| | `c10clk-...fpncimyu-ep162-s10-eval0.510.pt` | 0.5 | false | 162 | 0.510 | |
| | `c10clk-...3yqogp0e-ep161-s10-eval0.509.pt` | 0.1 | false | 161 | 0.509 | |
| | `c10clk-...zkz6ansr-ep158-s10-eval0.496.pt` | 0.1 | true | 158 | 0.496 | |
| | `c10clk-...1vleof96-ep160-s10-eval0.488.pt` | 0.5 | true | 160 | 0.488 | |
|
|
| Chance is 0.500. All four reached stage 10 by epoch 50 β three times sooner than the adaptive |
| arms β and none exceeded 0.537 at any point in ~160 epochs. They are published because the |
| depth-10 claim rests on this comparison: same task, same model, same `reset_optimizer=true`, |
| differing only in how stages advance. |
|
|
| ## What made depth 10 reachable |
|
|
| Two changes over the standard recipe, from a 2x2x2x2 factorial plus this baseline: |
|
|
| 1. **`reset_optimizer=true`** β rebuild AdamW every epoch, discarding both moment estimates. |
| Necessary: all four adaptive arms with it reached stage 10 and >0.96 eval; **no arm |
| without it passed stage 7 or 0.07 eval**, given ~2x the epochs. The curriculum keeps |
| shifting the input distribution, and stale second moments appear to misscale the new |
| stage's gradients. |
| 2. **Accuracy-driven staging** (`staging: revisit`, threshold 0.9, patience 5) β advance only |
| after a stage passes 5 consecutive epochs at its own budget, and fall back to any earlier |
| stage that regresses. |
| |
| Neither alone is enough. The `c10clk-*` arms have the optimizer reset and still sit at chance, |
| so the reset is necessary but not sufficient; and no arm without the reset got near stage 10 |
| under either schedule. Arriving at the final stage early is worth nothing if the stages were |
| never learned on the way. |
| |
| `uniform_prob` and `shuffle_nodes` only modulate how fast the schedule progresses; neither |
| rescues a run without `reset_optimizer`. |
| |
| ## Caveats |
| |
| - **Snapshots of a live oscillation, not converged models.** The revisit scheduler repeatedly |
| drops back to an earlier stage, and eval swings between ~0.3 and 1.000 before recovering. |
| These are caught at stage 10; they are not best-ever weights, and no LR decay was used. |
| - **Depth 10, not depth 10 held.** The 1.000 recurs across many epochs rather than once, but |
| "solves chain-10" describes a peak becoming a plateau. |
| - **2 layers beats 4.** In the same factorial no 4-layer arm passed stage 7 (best eval 0.17). |
| - Trained on a synthetic 40-token symbolic vocabulary; not a language model. |
|
|
| ## Loading |
|
|
| ```python |
| import torch |
| from huggingface_hub import hf_hub_download |
| |
| path = hf_hub_download("seyedparsa/lyot-chain10", |
| "c10-L2-u0.5-rtrue-strue-lyot-chain10_ucou7ar1-ep157-s10-eval0.999.pt") |
| ckpt = torch.load(path, map_location="cpu", weights_only=False) |
| print(ckpt["epoch"], ckpt["stage"], ckpt["metrics"]["eval/acc"]) |
| state = ckpt["model"] |
| ``` |
|
|
| Config: `n_layer=2, n_head=8, n_embd=768, n_positions=1024`, `method=coconut`, |
| `curriculum=path`, `c_thought=1`, `max_latent_stage=10`, `lr=1e-4`, `batch_size=128`. |
|
|