OliverSundaram commited on
Commit
d83d5d1
·
verified ·
1 Parent(s): a0e07ff

Add dense and top-2-of-4 MoE checkpoints, tokenizer, and benchmark assets

Browse files
README.md ADDED
@@ -0,0 +1,207 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ license: mit
3
+ language:
4
+ - en
5
+ library_name: transformers
6
+ pipeline_tag: text-generation
7
+ inference: false
8
+ datasets:
9
+ - nampdn-ai/tiny-textbooks
10
+ tags:
11
+ - mixture-of-experts
12
+ - moe
13
+ - from-scratch
14
+ - ablation
15
+ - research
16
+ ---
17
+
18
+ # MoE-Study — Dense vs. Mixture-of-Experts, matched active parameters
19
+
20
+ Two decoder-only language models trained **from scratch** under identical conditions, differing in
21
+ exactly one thing: whether the feed-forward block is a **dense MLP** or a **sparse top-2-of-4 MoE**.
22
+
23
+ Both checkpoints live in this one repo:
24
+
25
+ | Subfolder | Model | Total params | Active params/token |
26
+ |---------------------|----------------|--------------|---------------------|
27
+ | [`dense/`](./dense) | Dense FFN | 150.1M | 150.1M |
28
+ | [`moe/`](./moe) | Top-2-of-4 MoE | 206.8M | ~150.1M |
29
+
30
+ The MoE's active-parameter count matches Dense **by construction** — 2 of 4 experts at half the hidden
31
+ size means identical compute per token. The MoE only spends more *memory* for extra capacity.
32
+
33
+ Full write-up, training code, and evaluation harness:
34
+ **[github.com/OliverSundaram/MoE-Study](https://github.com/OliverSundaram/MoE-Study)**
35
+
36
+ ---
37
+
38
+ ## ⚠️ These are research artifacts, not usable models
39
+
40
+ Read this before downloading.
41
+
42
+ - Trained for **one epoch** on ~40.7M tokens — neither model is close to converged.
43
+ - **WikiText word perplexity is 551 (Dense) and 1,378 (MoE).** Generations are largely incoherent.
44
+ - **0.0% on LAMBADA** for both — at the task floor.
45
+ - No instruction tuning, no RLHF, no safety filtering of any kind.
46
+
47
+ They exist to answer one narrow question: *at matched active compute and matched budget, does sparsity
48
+ help?* They are not fit for any downstream use.
49
+
50
+ ---
51
+
52
+ ## Getting the weights
53
+
54
+ These are a custom architecture, not a variant of an existing one. The modeling code is not included
55
+ here, so `from_pretrained` on this repo alone will not build the model.
56
+
57
+ Clone [the GitHub repo](https://github.com/OliverSundaram/MoE-Study) — it carries the model definition
58
+ and loading instructions, and points back at these subfolders for the weights.
59
+
60
+ ---
61
+
62
+ ## Model details
63
+
64
+ ### Shared architecture
65
+
66
+ Both models are the same custom decoder-only transformer:
67
+
68
+ | | |
69
+ |---------------------|--------------------------------------------------------------------|
70
+ | Layers | 12 |
71
+ | Attention heads | 12 |
72
+ | Embedding dim | 768 |
73
+ | Context length | 1024 |
74
+ | Vocabulary | 50,257 (GPT-2 tokenizer) |
75
+ | Attention | **Multi-Query** — one shared K/V projection across all query heads |
76
+ | Normalization | Custom pre-norm (learned scale + shift) |
77
+ | Position embeddings | Learned absolute |
78
+ | Weight tying | None — separate input embedding and output head |
79
+
80
+ ### The one difference
81
+
82
+ | | `dense/` | `moe/` |
83
+ |--------------|------------------|------------------------------------------------|
84
+ | FFN block | 2-layer GELU MLP | 4 experts, top-2 routed |
85
+ | `hidden_dim` | 3072 | 1536 (per expert) |
86
+ | Router | — | linear → softmax → top-2, renormalized |
87
+ | Aux loss | — | load-balancing term, summed over all 12 layers |
88
+
89
+ Both models share the **same** unmodified GPT-2 tokenizer, stored once at the repo root.
90
+
91
+ ---
92
+
93
+ ## Training
94
+
95
+ Identical for both models. Single consumer GPU, no cloud.
96
+
97
+ | Setting | Value |
98
+ |---------------|----------------------------------------------------------------------------------------|
99
+ | Data | [`nampdn-ai/tiny-textbooks`](https://huggingface.co/datasets/nampdn-ai/tiny-textbooks) |
100
+ | Tokens | 39,717 chunks × 1024 = **~40.67M** |
101
+ | Epochs | **1** (19,858 steps) |
102
+ | Batch size | 2 × grad accum 4 = effective **8** |
103
+ | Optimizer | AdamW, lr `3e-4`, weight decay `0.1` (no decay on 1-D params) |
104
+ | Schedule | `OneCycleLR`, cosine, 3% warmup |
105
+ | Grad clipping | max-norm `1.0` |
106
+ | Precision | AMP autocast + `GradScaler` |
107
+ | Seed | 42 |
108
+ | Hardware | 1× NVIDIA RTX 4060, 8 GB VRAM |
109
+ | Wall-clock | ~44.6 min (Dense) · ~59.8 min (MoE) |
110
+
111
+ ### Final losses
112
+
113
+ | | Dense | MoE |
114
+ |----------------------------|-----------|-----------|
115
+ | Train loss (final step) | 5.166 | 5.936 |
116
+ | **Test loss (pure LM)** | **5.063** | **5.911** |
117
+ | Test loss (+ unscaled aux) | n/a | 17.91 |
118
+
119
+ Dense has the lower loss at **every** checkpoint.
120
+
121
+ ---
122
+
123
+ ## Evaluation
124
+
125
+ All benchmarks via [lm-evaluation-harness](https://github.com/EleutherAI/lm-evaluation-harness) on the
126
+ final checkpoints.
127
+
128
+ | Benchmark | Shots | Metric | Dense | MoE | abs(Δ) | Winner |
129
+ |------------------|-------|-------------------|-----------|-----------|--------|----------|
130
+ | ARC-Easy | 0 | `acc` | **29.2%** | 27.4% | 1.8 | 🔵 Dense |
131
+ | PIQA | 0 | `acc` | **55.0%** | 54.1% | 0.9 | 🔵 Dense |
132
+ | WikiText | 0 | `word_perplexity` | **551.0** | 1,377.8 | 826.8 | 🔵 Dense |
133
+ | LAMBADA (OpenAI) | 0 | `acc` | 0.0% | 0.0% | 0.0 | ⚪ Tie |
134
+ | WinoGrande | 5 | `acc` | 50.2% | **50.7%** | 0.5 | 🟠 MoE |
135
+ | HellaSwag | 10 | `acc_norm` | 24.9% | **25.1%** | 0.2 | 🟠 MoE |
136
+ | ARC-Challenge | 25 | `acc_norm` | 22.9% | **23.0%** | 0.1 | 🟠 MoE |
137
+
138
+ **How to read this:**
139
+
140
+ - Dense wins on everything sensitive to raw LLM quality — perplexity, ARC-Easy, PIQA.
141
+ - WinoGrande, HellaSwag, and ARC-Challenge are won by MoE, but with such a negligible difference, that they could be considered to have an equal accuracy
142
+
143
+ ### Inference speed
144
+
145
+ Greedy decoding, 32-token prompt → 64 new tokens, 5 trials, 2 warmup, no KV cache.
146
+
147
+ | Model | Tokens/sec | Total params | Active params/token |
148
+ |-------|-------------------|--------------|---------------------|
149
+ | Dense | **106.49 ± 0.30** | 150.1M | 150.1M |
150
+ | MoE | 34.40 ± 0.08 | 206.8M | ~150.1M |
151
+
152
+ MoE is **~3.1× slower** despite matched active compute — an artifact of unoptimized expert dispatch, not
153
+ a property of the architecture.
154
+
155
+ <details>
156
+ <summary><b>Benchmark charts</b></summary>
157
+
158
+ ![ARC-Easy](./assets/arc_easy.png)
159
+ ![PIQA](./assets/piqa.png)
160
+ ![WikiText](./assets/wikitext.png)
161
+ ![LAMBADA](./assets/lambada_openai.png)
162
+ ![WinoGrande](./assets/winogrande.png)
163
+ ![HellaSwag](./assets/hellaswag.png)
164
+ ![ARC-Challenge](./assets/arc_challenge.png)
165
+ ![Speed](./assets/speed.png)
166
+ </details>
167
+
168
+ ---
169
+
170
+ ## Findings
171
+
172
+ **1. Dense won every metric that wasn't already at chance.**
173
+ Most clearly on WikiText perplexity — 551 vs 1,378, a 2.5× gap.
174
+
175
+ **2. The routing math is correct.**
176
+ Active parameters match Dense almost exactly. Matched active compute simply didn't buy matched quality
177
+ at this budget.
178
+
179
+ **3. Routing stayed balanced.**
180
+ The load-balancing term sat on its theoretical floor, so the MoE's gap is not explained by experts
181
+ collapsing onto each other.
182
+
183
+ **4. Extra capacity needs extra tokens.**
184
+ The MoE has 38% more parameters but saw the same ~40.7M tokens — likely far too few to train 4 experts
185
+ per layer, each seeing only a routed fraction of the stream.
186
+ ---
187
+
188
+ ## Citation
189
+
190
+ ```bibtex
191
+ @misc{sundaram2026moestudy,
192
+ author = {Sundaram, Oliver},
193
+ title = {MoE-Study: Dense vs. Mixture-of-Experts at Matched Active Parameters},
194
+ year = {2026},
195
+ url = {https://github.com/OliverSundaram/MoE-Study}
196
+ }
197
+ ```
198
+
199
+ ## Acknowledgments
200
+
201
+ - [lm-evaluation-harness](https://github.com/EleutherAI/lm-evaluation-harness) (EleutherAI) — evaluation
202
+ - [nampdn-ai/tiny-textbooks](https://huggingface.co/datasets/nampdn-ai/tiny-textbooks) — training corpus
203
+ - [Hugging Face `transformers`](https://github.com/huggingface/transformers) — base classes and tokenizer
204
+
205
+ ## License
206
+
207
+ MIT
assets/arc_challenge.png ADDED
assets/arc_easy.png ADDED
assets/hellaswag.png ADDED
assets/lambada_openai.png ADDED
assets/piqa.png ADDED
assets/speed.png ADDED
assets/wikitext.png ADDED
assets/winogrande.png ADDED
dense/config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "LLM"
4
+ ],
5
+ "context_length": 1024,
6
+ "dtype": "float32",
7
+ "emb_dim": 768,
8
+ "hidden_dim": 3072,
9
+ "is_moe": false,
10
+ "model_type": "custom_llm",
11
+ "n_experts": null,
12
+ "n_heads": 12,
13
+ "n_layers": 12,
14
+ "qkv_bias": false,
15
+ "top_k": null,
16
+ "transformers_version": "5.15.0",
17
+ "vocab_size": 50257
18
+ }
dense/final_state.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:ac21bb0a177dbeea395f7fc451c6dc10b079ddebaa971ab4ff976eac00ecbf4b
3
+ size 1201509219
dense/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:f1143cf1b87fa9e4cc8504f31a87058889922e4836e3907bd028e8db56ef2ab0
3
+ size 600351628
moe/config.json ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "architectures": [
3
+ "LLM"
4
+ ],
5
+ "context_length": 1024,
6
+ "dtype": "float32",
7
+ "emb_dim": 768,
8
+ "hidden_dim": 1536,
9
+ "is_moe": true,
10
+ "model_type": "custom_llm",
11
+ "n_experts": 4,
12
+ "n_heads": 12,
13
+ "n_layers": 12,
14
+ "qkv_bias": false,
15
+ "top_k": 2,
16
+ "transformers_version": "5.15.0",
17
+ "vocab_size": 50257
18
+ }
moe/final_state.pt ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:8107ca89b5111e58627130c68161136a9000ed0b342a1593ea4db05d8d7b9c00
3
+ size 1655436555
moe/model.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:de50a32d2c285961cd36bd51a5f4fe7e5593897318d31ab665f4d1573c1854d2
3
+ size 827267812
tokenizer.json ADDED
The diff for this file is too large to render. See raw diff
 
tokenizer_config.json ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "add_prefix_space": false,
3
+ "backend": "tokenizers",
4
+ "bos_token": "<|endoftext|>",
5
+ "eos_token": "<|endoftext|>",
6
+ "errors": "replace",
7
+ "is_local": false,
8
+ "local_files_only": false,
9
+ "model_max_length": 1024,
10
+ "pad_token": null,
11
+ "tokenizer_class": "GPT2Tokenizer",
12
+ "unk_token": "<|endoftext|>"
13
+ }