Views
No views yet
r times,
448-dim, 9,064,608 parameters, trained from scratch on FineWeb next-token
prediction. T-Lab test task submission. Run full_control90_kaggle, 90.0M tokens, step 43944.| metric | value |
|---|---|
| CE @ 1 loop | 3.9622 |
| best val CE | 3.6599 (at 10 loops) |
| val perplexity | 38.86 |
| bits/byte | 1.5829 (at 3.3358 bytes/token) |
| useful-depth plateau | [6, 17] on the dense 1..64 eval grid |
| loop gain (CE@1 − CE@best) | 0.3023 |
METHOD.md §2 recommends supervision annealing — dense supervision for most of training, then
terminal-loop-only for the final ~10% of steps. These weights do not implement it. They are the
dense control: supervise_k = 5 throughout, no supervise_k_final, no supervise_switch_frac.rec_sw90_s2); no 90M one does. See METHOD.md §4.ΔCE@1 = +0.2263). It wins the
loop-gain statistic by making one loop worse, not by making depth worth more.report.md §4.6b and §6.0b/D3, and
submission/METHOD.md §4.sum(v.numel() for v in state_dict.values()) returns 10,899,616, which is over the task's 10M
cap. That is an artifact of weight tying, this architecture's central feature: lm_head and
embed are the same nn.Parameter under two names, so a state_dict sum counts the tied embedding
twice. The difference is exactly vocab x hidden = 1,835,008.sum(p.numel() for p in m.parameters()) # 9,064,608 <- the real count, and what every number usesmodel.pt — weights (torch.load, weights_only=False; contains model, model_cfg, train_cfg)tokenizer.json — the vocabulary these weights were trained with. Do not substitute another
one and do not retrain it: a mismatch raises nothing and reports CE ≈ ln(4096) =
8.3178, i.e. chance, which looks like a broken model rather than a broken setup.model.py — the architecture, so this checkpoint loads without cloning the GitHub repo.python src/check_tokenizer_identity.py <this checkpoint> --expect-ce1 3.96221import torch
2from model import Config, LoopedTransformer
3ck = torch.load("model.pt", map_location="cpu", weights_only=False)
4m = LoopedTransformer(Config(**ck["model_cfg"])); m.load_state_dict(ck["model"]); m.eval()
5logits_per_loop, state_norms = m(input_ids, n_loops=10, return_all_loops=True)| loop | 1 | 8 | 16 | 64 |
|---|---|---|---|---|
| ‖h‖ | 466.6 | 2334.4 | 3977.3 | 12424.4 |
src/radial_clamp.py on this checkpoint, which does it for you.{"vocab_size": 4096, "hidden_size": 448, "n_heads": 4, "n_kv_heads": 2, "head_dim": 112, "intermediate_size": 1344, "layers_per_loop": 3, "n_prelude": 0, "n_coda": 0, "rms_norm_eps": 1e-06, "rope_theta": 10000.0, "max_position_embeddings": 512, "readout_mode": "norm", "convex_gate": false, "explore_noise": 0.0, "explore_anneal": true, "fixed_gate": null, "truncate_bptt": null, "state_renorm": false, "inject_mode": "additive", "depth_init": true, "residual_scale": null, "scale_clock": false, "gate_alpha_init": 0.874, "n_loop_eff": 24, "cond_mode": "none", "cond_lora_rank": 4, "cond_lora_branches": 4, "cond_fixed_branch": null, "kv_untie_buckets": 1, "depth_gate_mode": "none", "xsa": false, "kv_window": 1}report.md for the full ablation set, the negative results, and the
failure log (§6.0).