Add TRM-Nano README with architecture details and usage"
Browse files
trm_solver/trm_nano/README.md
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# TRM-Nano: Tiny Recursive Model for NeuroGolf 2026
|
| 2 |
+
|
| 3 |
+
Based on [Samsung TRM](https://arxiv.org/abs/2510.04871) (ARC Prize 2025 1st Place Paper Award).
|
| 4 |
+
|
| 5 |
+
## Architecture
|
| 6 |
+
|
| 7 |
+
| Parameter | Value | Notes |
|
| 8 |
+
|-----------|-------|-------|
|
| 9 |
+
| hidden_size | 96 | 24 per head |
|
| 10 |
+
| num_heads | 4 | non-causal attention |
|
| 11 |
+
| num_layers | 2 | single block, weight-shared |
|
| 12 |
+
| expansion | 4 | SwiGLU FFN |
|
| 13 |
+
| H_cycles (T) | 3 | outer recursions |
|
| 14 |
+
| L_cycles (n) | 4 | inner recursions per T |
|
| 15 |
+
| Total depth | 15 passes | T×(n+1) through same 2-layer block |
|
| 16 |
+
| Params | ~200K | ~0.8 MB FP32 ONNX |
|
| 17 |
+
| puzzle_emb | 8 tokens | learned per-task |
|
| 18 |
+
|
| 19 |
+
## Key Design Decisions
|
| 20 |
+
|
| 21 |
+
1. **Weight sharing**: Single 2-layer block recursed 15 times. This is the core TRM insight — recursive depth > width.
|
| 22 |
+
2. **Unrolled recursion**: No `Loop`/`Scan` ops in ONNX. All 15 passes hardcoded sequentially.
|
| 23 |
+
3. **Post-norm residual**: `x = rms_norm(x + attn(x))` then `x = rms_norm(x + mlp(x))`.
|
| 24 |
+
4. **Dual latent**: `z_H` (answer) and `z_L` (reasoning). L-cycles update reasoning with input context, then one H-update refines the answer.
|
| 25 |
+
5. **Input injection**: `z_L` receives `z_H + x_embed` as injection. `z_H` receives `z_L` only (no input). This forces `z_H` to represent a complete answer.
|
| 26 |
+
|
| 27 |
+
## NeuroGolf I/O
|
| 28 |
+
|
| 29 |
+
- **Input**: `[1, 10, 30, 30]` float32 one-hot → argmax → flat 900 tokens (+2 shift)
|
| 30 |
+
- **Output**: logits → softmax over color channels → `[1, 10, 30, 30]`
|
| 31 |
+
- **ONNX size**: ~800 KB (well within 1.44 MB limit)
|
| 32 |
+
|
| 33 |
+
## Usage
|
| 34 |
+
|
| 35 |
+
### Single task training
|
| 36 |
+
```bash
|
| 37 |
+
cd trm_solver/trm_nano
|
| 38 |
+
python train_task.py \
|
| 39 |
+
--task_file /path/to/task.json \
|
| 40 |
+
--output_dir onnx_out/ \
|
| 41 |
+
--epochs 500 \
|
| 42 |
+
--hidden_size 96 \
|
| 43 |
+
--device cuda
|
| 44 |
+
```
|
| 45 |
+
|
| 46 |
+
### From Kaggle notebook
|
| 47 |
+
```python
|
| 48 |
+
import sys
|
| 49 |
+
sys.path.insert(0, '/kaggle/input/arc-agi-code/trm_solver/trm_nano')
|
| 50 |
+
|
| 51 |
+
from model import TRMNano, TRMNanoConfig
|
| 52 |
+
from train_task import train_on_task, evaluate_task, export_onnx
|
| 53 |
+
|
| 54 |
+
config = TRMNanoConfig(hidden_size=96, H_cycles=3, L_cycles=4)
|
| 55 |
+
model = train_on_task(task_data, config, epochs=500, device="cuda")
|
| 56 |
+
export_onnx(model, "task_id.onnx")
|
| 57 |
+
```
|
| 58 |
+
|
| 59 |
+
## Training Details
|
| 60 |
+
|
| 61 |
+
- **Augmentation**: 8 dihedral transforms × random color permutation (keep 0 fixed) × random translation = ~1000 augmented views per task
|
| 62 |
+
- **Optimizer**: AdamW, lr=1e-3, weight_decay=0.1, betas=(0.9, 0.95)
|
| 63 |
+
- **Schedule**: Cosine annealing
|
| 64 |
+
- **EMA**: decay=0.999 (final weights use EMA)
|
| 65 |
+
- **Loss**: Cross-entropy on output tokens, ignore PAD positions
|
| 66 |
+
- **Evaluation**: Majority voting over 64 augmented forward passes with inverse transform
|
| 67 |
+
|
| 68 |
+
## Comparison to Full TRM
|
| 69 |
+
|
| 70 |
+
| | Full TRM | TRM-Nano |
|
| 71 |
+
|---|---|---|
|
| 72 |
+
| hidden_size | 512 | 96 |
|
| 73 |
+
| params | 7M | ~200K |
|
| 74 |
+
| T×n | 3×6=18+3=21 | 3×4=12+3=15 |
|
| 75 |
+
| training | 3 days 4×H100 | ~5 min/task single GPU |
|
| 76 |
+
| ARC-1 score | 44.6% (all tasks) | TBD (per-task) |
|
| 77 |
+
| ONNX size | 26 MB | ~0.8 MB |
|
| 78 |
+
|
| 79 |
+
## Files
|
| 80 |
+
|
| 81 |
+
| File | Purpose |
|
| 82 |
+
|------|---------|
|
| 83 |
+
| `model.py` | TRM-Nano architecture (PyTorch) |
|
| 84 |
+
| `train_task.py` | Per-task training + eval + ONNX export |
|
| 85 |
+
|
| 86 |
+
## References
|
| 87 |
+
|
| 88 |
+
- [Less is More: Recursive Reasoning with Tiny Networks](https://arxiv.org/abs/2510.04871)
|
| 89 |
+
- [Samsung-TRM code](https://huggingface.co/wtfmahe/Samsung-TRM)
|