bfuzzy1 commited on
Commit
d62ba2f
·
verified ·
1 Parent(s): 5da4869

Upload folder using huggingface_hub

Browse files
.gitattributes CHANGED
@@ -33,3 +33,4 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
 
 
33
  *.zip filter=lfs diff=lfs merge=lfs -text
34
  *.zst filter=lfs diff=lfs merge=lfs -text
35
  *tfevents* filter=lfs diff=lfs merge=lfs -text
36
+ loss_datamix.png filter=lfs diff=lfs merge=lfs -text
README.md ADDED
@@ -0,0 +1,213 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Rodan-10M
2
+
3
+ A ~11M-parameter language model trained start to finish on one Apple M2 with MLX. The aim was a tiny model
4
+ that actually holds up for its size, scored on how much it gets per parameter rather than raw leaderboard rank.
5
+
6
+ | Model | Stage | Purpose |
7
+ |---|---|---|
8
+ | **Rodan-10M-Base** | pretraining | foundation: commonsense + knowledge |
9
+ | Rodan-10M-Chat *(in training)* | instruction fold | chat / instruction following |
10
+ | Rodan-10M-Reasoning *(in training)* | recursive depth + CoT fold | verifiable math + reasoning |
11
+ | Rodan-10M-Latent *(planned)* | latent reasoning | in-head compute, no CoT tokens |
12
+
13
+ This card covers the base model only. The chat, reasoning, and latent stages are separate models with their
14
+ own repos and cards.
15
+
16
+ ## Architecture
17
+
18
+ Decoder-only transformer, wide per layer (the proportions take a cue from Gemma-style edge models), 11.46M params.
19
+
20
+ ```
21
+ vocab_size 8192 byte-level BPE
22
+ dim 320
23
+ n_layers 8
24
+ n_heads 8 head_dim 40
25
+ n_kv_heads 1 MQA (8 query heads share 1 KV head)
26
+ ffn_hidden 768 SwiGLU
27
+ max_seq_len 512
28
+ norm RMSNorm (eps 1e-5)
29
+ position RoPE (base 200000), applied after QK-norm
30
+ tied_embeddings true
31
+ value_residual true mix layer-0 values into later layers
32
+ ple_rank 16 factorized per-layer value-embeddings
33
+ lrm true learnable per-row/col weight multipliers (Falcon LRM)
34
+ recurse 1 re-run the shared block stack N times (1 = base; >1 used by the reasoning stage)
35
+ ```
36
+
37
+ The `recurse` knob is a recursive-depth mechanism (Universal-Transformer-style weight sharing, inspired by
38
+ the TRM/HRM "tiny recursive reasoning" line). Setting `recurse=N` runs the same 8 blocks N times over the
39
+ residual stream, so you get the effective depth of `8·N` layers at **zero extra parameters**. The base runs
40
+ `recurse=1` (it's a plain 8-layer model). The reasoning stage warm-starts these weights and trains at
41
+ `recurse=2` (16 effective layers, still 10.41M params), letting the model spend more compute per token on
42
+ hard problems without growing. It is not the full TRM/HRM algorithm (no separate answer/latent states, no
43
+ deep supervision); it's the shared-recursion idea applied to an autoregressive LM.
44
+
45
+ It was built in two passes: a from-scratch base on 262M tokens, then a warm-start continue on another
46
+ 115M tokens that adds LRM, raises the RoPE base from 10k to 200k, and mixes in 21% arithmetic/reasoning data
47
+ (Falcon's reasoning-in-pretraining idea). That second pass is the 11.46M v6 checkpoint.
48
+
49
+ ```mermaid
50
+ flowchart TB
51
+ ids["token ids"]:::io --> emb["Embedding 8192x320 (tied)"]:::emb
52
+ emb --> blk["8 x ModernBlock"]:::core
53
+ blk --> fn["RMSNorm"]:::norm
54
+ fn --> head["tied head (x @ Wemb^T)"]:::emb
55
+ head --> out["logits 8192"]:::io
56
+
57
+ subgraph ModernBlock["ModernBlock (x8)"]
58
+ direction TB
59
+ x(["x"]):::res --> n1["RMSNorm"]:::norm
60
+ n1 --> qkv["q/k/v projection<br/>MQA: 8 q-heads, 1 kv-head, head_dim 40"]:::attn
61
+ qkv -->|"q, k"| qk["QK-norm to RoPE"]:::attn
62
+ qkv -->|"v"| vm["+ value-PLE (per-layer)<br/>+ value-residual (layer-0 v)"]:::attn
63
+ qk --> sdpa{{"scaled dot-product<br/>attention"}}:::attn
64
+ vm --> sdpa
65
+ sdpa --> wo["output projection"]:::attn
66
+ x --> a1(["+"]):::res
67
+ wo --> a1
68
+ a1 --> n2["RMSNorm"]:::norm
69
+ n2 --> ffn["SwiGLU FFN<br/>320 to 768 to 320"]:::ffn
70
+ a1 --> a2(["+"]):::res
71
+ ffn --> a2
72
+ a2 --> xo(["x out"]):::res
73
+ end
74
+
75
+ classDef io fill:#ffb73d,stroke:#fff,color:#0a0703,font-weight:bold
76
+ classDef emb fill:#e08a2b,stroke:#ffd98a,color:#0a0703
77
+ classDef core fill:#c4631a,stroke:#ffd98a,color:#fff
78
+ classDef attn fill:#1f4e6b,stroke:#5ad1ff,color:#dff4ff
79
+ classDef ffn fill:#5c3a0c,stroke:#ffb73d,color:#ffd98a
80
+ classDef norm fill:#231603,stroke:#a86d18,color:#ffd98a
81
+ classDef res fill:#5ad1ff,stroke:#fff,color:#0a0703,font-weight:bold
82
+ ```
83
+
84
+ Pre-norm residual blocks: `x += Attn(RMSNorm(x))`, then `x += SwiGLU(RMSNorm(x))`. Layer-0's attention
85
+ values feed the value-residual mix in every later layer, and each layer also adds its own low-rank value-PLE.
86
+
87
+ Why these specific choices at 11M, where every parameter has to earn its place:
88
+
89
+ - 8k vocab with tied embeddings. Only about 23% of the params sit in the embedding table, versus roughly
90
+ 70% for a 49k-vocab model this size. That frees most of the budget for the layers that do the computing.
91
+ - MQA, because it's the cheapest attention that still works, which leaves params for depth and embeddings.
92
+ - value-residual does most of the heavy lifting. A checkpoint probe shows later layers blending 77-99% of
93
+ layer-0's values, so it acts as a shared value memory and a gradient highway at once.
94
+ - LRM (learnable row/col multipliers) probed about 20% off identity, so the model is genuinely using it.
95
+ - QK-norm for attention stability, from the nanoGPT-speedrun stack.
96
+ - value-PLE we tried and then removed. The probe found it dead: 0.2% contribution, weight-decayed to near
97
+ zero. v9 drops it and lands at 10.41M with no loss in quality.
98
+
99
+ ## Training
100
+
101
+ - Optimizer: Muon on the 2D hidden weights, AdamW on the embeddings, norms, and LRM multipliers, joined
102
+ through MultiOptimizer, cosine LR, grad-clip 1.0.
103
+ - Framework: MLX on Apple Silicon, with an `mx.compile`d step. About 0.6-0.7 it/s on one fanless M2 MacBook Air.
104
+ - Data: a warm-start chain of short stages, fresh tokens each time so nothing gets re-looped and memorized.
105
+ Here are the base (v6) and the challenger that followed it (v9):
106
+
107
+ | Source | v6 base (mixed5) | v9 (mixed8) | Content |
108
+ |---|---|---|---|
109
+ | Cosmopedia v2 | 27% | 31% | synthetic textbooks → commonsense |
110
+ | dolmino-mix-1124 (pes2o + StackExchange) | 35% | 26% | academic papers + Q&A → knowledge/ARC |
111
+ | synthetic arithmetic (ArithMark-style) | 21% | 19% | computation → ArithMark |
112
+ | FineMath-4plus | 10% | 15% | math prose |
113
+ | science-QA (SciQ/OBQA/QASC/ARC-train) | 6% | 9% | science MC |
114
+ | **tokens** | ~0.38B | +0.12B fresh | curated, no raw web |
115
+
116
+ Two things we found out the hard way. First, adding FineWeb-Edu (45%, then 25%) lost to v6 both times, in
117
+ a clean monotonic line: raw web hurts at 11M. The model is too small to digest it, and the curated
118
+ synthetic-plus-academic mix wins instead. Second, the probe that killed value-PLE also confirmed
119
+ value-residual and LRM are doing real work. So v9 is the pure-curated, PLE-free version at 10.41M: it
120
+ drops both of the things we'd shown were dead weight and keeps the recipe that worked.
121
+
122
+ Training-compute efficiency, from the actual runs (perplexity vs cumulative FLOPs, `6·N·tokens`):
123
+
124
+ ![Perplexity vs Training Compute](flops_efficiency.png)
125
+
126
+ Intelligence per parameter (board avg vs log-params; the shaded region is above the size-fit line):
127
+
128
+ ![Intelligence per parameter](intelligence_per_param.png)
129
+
130
+ The fit runs over all 54 board models, with a residual σ of 3.07 that matches the board's own. Rodan v6
131
+ sits +0.31σ above the size-fit line, ahead of liodon at +0.14 and well clear of the per-param
132
+ underachievers like GPT-2 (124M, far below). It does this on roughly 1/50th the tokens of the leading
133
+ models, which train on about 25B.
134
+
135
+ Training loss and data mix, v6 vs v9:
136
+
137
+ ![Training loss and data mix](loss_datamix.png)
138
+
139
+ v9 starts from v6, drops the dead PLE down to 10.41M, and trains on the pure-curated mix. The result was a
140
+ tie: board avg 35.70 against v6's 35.80, a 0.10 gap that's well inside the noise, at 9% fewer parameters. It
141
+ gave up about 1.7 points of HellaSwag and picked up 2.0 on ArithMark (28.4, the folded arithmetic finally
142
+ showing), and the per-param number came out about even too (~+0.32σ vs v6's +0.31σ). Two conclusions fall
143
+ out of that. PLE really was dead weight, since cutting 1.05M params changed nothing. And ~35.8 looks like a
144
+ real ceiling for an 11M model on this board: raw web sinks it, the leaner pure-curated mix holds it, and
145
+ nothing we tried pushed past it. So v6 stays the packaged base, and the next gains have to come from
146
+ capability stages rather than more base pretraining. Unique tokens stay around 0.5B the whole way, about
147
+ 1/50th of what the leaders use.
148
+
149
+ ## Evaluation
150
+
151
+ Zero-shot through lm-eval-harness, with a custom MLX backend for `loglikelihood`. We use acc_norm for the
152
+ length-sensitive multiple-choice tasks (HellaSwag, ARC, OpenBookQA) and plain acc otherwise.
153
+
154
+ Zero-shot, limit 1000 examples per task. Board avg = (HellaSwag + (ARC-E + ARC-C)/2 + PIQA + ArithMark) / 4.
155
+
156
+ | Task | Metric | Score | Random |
157
+ |---|---|---|---|
158
+ | SciQ | acc | 67.5 | 25 |
159
+ | PIQA | acc | 56.0 | 50 |
160
+ | COPA | acc | 55.0 | 50 |
161
+ | ARC-Easy | acc_norm | 35.6 | 25 |
162
+ | HellaSwag | acc_norm | 31.8 | 25 |
163
+ | OpenBookQA | acc_norm | 27.0 | 25 |
164
+ | ArithMark-2 | acc | 26.4 | 25 |
165
+ | ARC-Challenge | acc_norm | 22.4 | 25 |
166
+ | Winogrande | acc | 49.8 | 50 |
167
+ | LogicMark | acc | 44.8 | 25 |
168
+ | BoolQ | acc | 37.6 | ~50 |
169
+ | CommonsenseQA | acc | 20.7 | 20 |
170
+ | **Board avg (÷4)** | | **35.80** | |
171
+
172
+ For context, it beats the <10M leader on about 1/65th the tokens:
173
+
174
+ | Model | Params | Tokens | Board avg (÷4) |
175
+ |---|---|---|---|
176
+ | **Rodan-10M-Base (v6)** | 11.46M | ~0.38B | **35.80** |
177
+ | Liodon SLM-10M | 10M | 25B | 35.09 |
178
+ | GPT-S-5M (Axiomic) | 5.2M | 25B | 34.75 |
179
+
180
+ ![v6 benchmarks](v6_v9_metrics.png)
181
+
182
+ v6 lands around rank 22 of 54 and +0.31σ above the size-fit line, ahead of liodon at +0.14. The v9
183
+ challenger (PLE-free, 10.41M, pure-curated) tied it: 35.70 board avg at 9% fewer params, and about even on
184
+ per-param too (~+0.32σ). v9 confirmed the ~11M ceiling and that PLE was dead weight, but since it didn't
185
+ move the board, v6 stays the base. From here the work moves to the capability stages.
186
+
187
+ What the model is actually like: it holds up well for 11M on commonsense and science multiple-choice. SciQ
188
+ (67.5) beats GPT-2-124M, and PIQA (56.0), ARC-Easy (35.6), HellaSwag (31.8), and COPA (55.0) are all clearly
189
+ above random. Arithmetic has crept off the random floor (ArithMark 26.4) thanks to the folded-in computation
190
+ data, though it's a modest lift and actually generating arithmetic is still weak. On the harder abstract
191
+ reasoning tasks (Winogrande, CommonsenseQA, ARC-Challenge, OpenBookQA) and on open-ended generation it's near
192
+ chance, partly a capacity ceiling at this size and partly loglikelihood length-bias. It's a solid base for
193
+ discrimination; the deeper reasoning is the job of the later reasoning and latent stages.
194
+
195
+ ## Limitations
196
+
197
+ - English only, ~11M params. This is a research and teaching base, not something to put in front of users or
198
+ trust for facts.
199
+ - It's reliable only on the easy commonsense and science multiple-choice where it beats random. On abstract
200
+ reasoning (Winogrande, CommonsenseQA, ARC-Challenge) and arithmetic it's at chance.
201
+ - No instruction tuning or safety alignment yet. It completes text; it does not follow instructions.
202
+ - Trained on about one epoch of a curated mix, so coverage of rare facts is thin compared to models trained
203
+ on far more tokens.
204
+
205
+ ## Files
206
+
207
+ A standard model repo: `model.safetensors` (weights), `tokenizer.json` (8k byte-level BPE), `config.json`.
208
+ Trained on a single Apple M2 with MLX in about six hours.
209
+
210
+ ## License
211
+
212
+ Weights are open. Data falls under the respective dataset licenses (Cosmopedia, dolmino-mix ODC-By, AllenAI
213
+ QA sets, FineMath).
config.json ADDED
@@ -0,0 +1,26 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "model_type": "rodan-modern",
3
+ "architecture": "ModernLM",
4
+ "framework": "mlx",
5
+ "params": 11460000,
6
+ "vocab_size": 8192,
7
+ "dim": 320,
8
+ "n_layers": 8,
9
+ "n_heads": 8,
10
+ "n_kv_heads": 1,
11
+ "head_dim": 40,
12
+ "ffn_hidden": 768,
13
+ "max_len": 512,
14
+ "rope_base": 200000.0,
15
+ "norm": "rmsnorm",
16
+ "norm_eps": 1e-5,
17
+ "activation": "swiglu",
18
+ "qk_norm": true,
19
+ "tied_embeddings": true,
20
+ "value_residual": true,
21
+ "ple_rank": 16,
22
+ "lrm": true,
23
+ "attention": "mqa",
24
+ "tokenizer": "byte-level BPE (8k), eot id 0",
25
+ "notes": "Custom MLX decoder-only transformer. Load with model_opt.ModernLM(ModernConfig(**fields)) + load_weights('model.safetensors'). See README."
26
+ }
flops_efficiency.png ADDED
intelligence_per_param.png ADDED
loss_datamix.png ADDED

Git LFS Details

  • SHA256: 7e9d97f8850d832b0d9df453df942a12839065a3f500b33f02ddefa05c42aedc
  • Pointer size: 131 Bytes
  • Size of remote file: 110 kB
model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:31dbd650d5e639f75a51b29ffdd4f463019741921cb83c96acfa72ade82c829c
3
+ size 45878253
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
v6_v9_metrics.png ADDED