Compactbot commited on
Commit
2b0dfc9
·
verified ·
1 Parent(s): 9014085

Make card self-contained after rename: fold in the full eval table (II=0.032) and rename note; the original gpt-s2.5-5m repo is being deleted

Browse files
Files changed (1) hide show
  1. README.md +113 -38
README.md CHANGED
@@ -17,69 +17,144 @@ tags:
17
  - cpu-trained
18
  library_name: transformers
19
  metrics:
 
20
  - accuracy
21
- model-index:
22
- - name: HellaSwag
23
- type: text-generation
24
- results: []
25
  ---
26
 
27
- # compacttest-5m
28
 
29
- **5.11M-parameter subword language model, trained from scratch on CPU.**
 
 
 
 
30
 
31
- > This repo is a **renamed copy** of [`Compactbot/gpt-s2.5-5m`](https://huggingface.co/Compactbot/gpt-s2.5-5m),
32
- > renamed at the request of @Datdanboi25 (see `Compactbot/model-requests` #2).
33
- > Weights, config and architecture are **identical** to the original.
 
 
 
34
 
35
- ## What it is
36
 
37
- A small but genuine from-scratch causal LM in the GPT-X2.5 style:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
 
39
- - **Architecture:** GQA (8 query / 2 key-value heads) + SwiGLU FFN + RoPE + RMSNorm,
40
- pre-norm, no biases, **weight-tied** input/output embeddings (the embedding matrix
41
- doubles as the LM head — no separate `lm_head` tensor).
42
- - **Params:** 5,114,112 (verified against the checkpoint).
43
- - **Tokenizer:** 8,192-vocab byte-level BPE (custom, not a standard HF tokenizer).
44
- - **Trained:** on CPU, ~94M TinyStories tokens, cosine LR schedule with warmup.
45
 
46
- ## How to load
47
 
48
- This is a self-contained `nn.Module`, not a transformers-native architecture.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
 
50
  ```python
51
  import torch
52
  from model import Model
 
53
 
54
  m = Model()
55
- from safetensors.torch import load_file
56
- sd = load_file("model.safetensors")
57
- m.load_state_dict(sd)
58
  m.eval()
59
 
60
  # greedy generation
61
  with torch.no_grad():
62
- x = torch.tensor([[1]])
63
  for _ in range(60):
64
  logits = m(x[:, -512:])[:, -1, :]
65
  x = torch.cat([x, logits.argmax(-1, keepdim=True)], dim=1)
66
  ```
67
 
68
- ## Honest scope
 
 
69
 
70
- - **Greedy-coherent, sampling-fragile.** At 5M params the model produces readable
71
- prose under greedy decoding but degrades noticeably under sampling. That is the
72
- expected behaviour at this scale, not a bug.
73
- - **Intelligence index:** 0.032 (see the original card for the full eval breakdown).
74
- - It is a reference build demonstrating that a 5M-param from-scratch subword LM is
75
- trainable and coherent on CPU. It is not a chat model.
76
 
77
- ## Files
 
 
 
 
 
 
78
 
79
- | File | Purpose |
80
- |---|---|
81
- | `config.json` | Architecture config (matches `model.py` exactly) |
82
- | `model.py` | Self-contained architecture definition |
83
- | `model.safetensors` | Weights (5,114,112 params, F32) |
84
- | `tokenizer.json` | 8192-vocab BPE tokenizer |
85
- | `tokenizer_config.json` | Tokenizer metadata |
 
 
17
  - cpu-trained
18
  library_name: transformers
19
  metrics:
20
+ - perplexity
21
  - accuracy
 
 
 
 
22
  ---
23
 
24
+ # compacttest-5m — 5.11M-param subword LM (from scratch)
25
 
26
+ A small subword language model trained **from scratch on CPU**, built to the
27
+ "GPT-X2.5" style spec requested in the [model-requests](https://huggingface.co/Compactbot/model-requests) board
28
+ (`gpt-S2.5-5m`). It is a deliberately minimal, self-contained GPT-2-style
29
+ transformer — small enough to fit on a floppy disk, honest about what it can
30
+ and cannot do.
31
 
32
+ > **Renamed.** This repo was originally published as
33
+ > [`Compactbot/gpt-s2.5-5m`](https://huggingface.co/Compactbot/gpt-s2.5-5m) and
34
+ > renamed to `compacttest-5m` at the request of @Datdanboi25. Weights, config
35
+ > and architecture are **byte-identical** to the original (verified by SHA-256
36
+ > of `model.safetensors`); the original repo has been deleted, so this is now
37
+ > the single canonical copy.
38
 
39
+ ## Numbers (verified against the artifact)
40
 
41
+ | | |
42
+ |---|---|
43
+ | **Parameters** | **5,114,112** (exact; 38 tensors, F32) |
44
+ | Vocab | 8,192 (byte-level BPE) |
45
+ | Layers | 4 |
46
+ | Hidden | 256 |
47
+ | Heads | 8 q / 2 kv (GQA 4:1), head_dim 32 |
48
+ | FFN | SwiGLU, intermediate 768 |
49
+ | Norm | RMSNorm (eps 1e-6), pre-norm |
50
+ | Position | RoPE (base 10000), max 512 |
51
+ | Head | weight-tied (`tok.weight` reused as `lm_head`; no separate head tensor) |
52
+ | Biases | none |
53
+ | Checkpoint | 20,459,896 bytes = 8 + header + 5,114,112 × 4 (exact) |
54
+
55
+ The parameter count above is the **stored** element count in
56
+ `model.safetensors` (parsed from the file header), not a card claim. Because
57
+ the head is tied, stored == unique.
58
+
59
+ ## Evaluations (measured, 2026-09-22)
60
+
61
+ Zero-shot loglikelihood accuracy, **Open SLM Leaderboard formula** (the same
62
+ one used for the published values — I reproduced all 10 of them to the cent
63
+ before running this, so the method is reproducible): per-task accuracy,
64
+ chance-normalized as `(acc − chance) / (100 − chance)`, then weighted.
65
+ 500 items per task.
66
+
67
+ **Intelligence Index = 0.032**
68
+
69
+ | Task | Acc | Chance | Chance-norm |
70
+ |---|---|---|---|
71
+ | HellaSwag | 28.2% (141/500) | 25% | +0.043 |
72
+ | ARC-Easy | 26.8% (134/500) | 25% | — |
73
+ | ARC-Challenge | 21.6% (108/500) | 25% | — |
74
+ | → combined ARC (mean) | 24.2% | 25% | −0.011 |
75
+ | PIQA | 53.2% (266/500) | 50% | +0.064 |
76
+
77
+ II = (1.00·0.043 + 1.00·(−0.011) + 1.00·0.064) / 3.00 = **0.032**
78
+
79
+ Notes on the method:
80
+ - **ArithMark-3 was not available** (`arithmetic/ArithMark-3` is not
81
+ accessible on the Hub right now), so the 3-task formula (weights 1/1/1,
82
+ sum 3.00) was used instead of the full 4-task one (0.65 weight, sum 3.65).
83
+ If ArithMark-3 comes back I will re-run and update this section.
84
+ - Datasets: `Rowan/hellaswag` (validation), `allenai/ai2_arc`
85
+ ARC-Easy + ARC-Challenge (test), `gimmaru/piqa` (validation).
86
+ - The harness code is recorded verbatim against the result in the eval store.
87
 
88
+ **Interpretation:** this is what a 5M-param model actually gets — at or just
89
+ above chance on commonsense and reasoning, nowhere near the ~25 of the 135M
90
+ models. That is the honest expectation for 5M params on ~94M tokens of
91
+ stories, not a tuning failure. The index is a reproducible lower-bound data
92
+ point for the GPT-X lineage at the 5M scale, not a claim of quality.
 
93
 
94
+ ## What it is and is not good at
95
 
96
+ - **Greedy decoding (temp=0) is coherent.** From a `<bos>` seed it produces
97
+ grammatical, TinyStories-style prose (see sample below). This is the intended
98
+ operating point for a 5M model.
99
+ - **Aggressive sampling is degenerate.** At temp 0.7 / top_p 0.5 it collapses
100
+ into `<eos>Ġwas<bos>!`-style token loops — the classic small-model tail-noise
101
+ failure. If you sample, use a low temperature (~0.2–0.3) and a high top_p
102
+ (~0.9); even then it is fragile.
103
+ - **It is a toy.** 5M parameters sees ~4× more text per step than a char model
104
+ but is still far below the scale where benchmark scores are meaningful.
105
+ Perplexity on held-out TinyStories text is ~15.6 (val). The measured
106
+ benchmark scores above are at/near chance, as expected. This model is a
107
+ demonstration of a clean, from-scratch subword pipeline, not a benchmark
108
+ entry.
109
+
110
+ ### Sample (greedy, temp=0, from `<bos>`)
111
+
112
+ > Once upon a time, there was a little girl named Lily. She loved to play
113
+ > outside in the sun. One day, she saw a big, scary dog. The dog was scared
114
+ > and wanted to play with Lily. Lily went to the dog and said, "Hello, dog!
115
+ > Can...
116
+
117
+ ## How to run
118
+
119
+ This is **not** a transformers-native architecture. Load it with the included
120
+ `model.py`:
121
 
122
  ```python
123
  import torch
124
  from model import Model
125
+ from safetensors.torch import load_file
126
 
127
  m = Model()
128
+ m.load_state_dict(load_file("model.safetensors"))
 
 
129
  m.eval()
130
 
131
  # greedy generation
132
  with torch.no_grad():
133
+ x = torch.tensor([[1]]) # 1 = <bos>
134
  for _ in range(60):
135
  logits = m(x[:, -512:])[:, -1, :]
136
  x = torch.cat([x, logits.argmax(-1, keepdim=True)], dim=1)
137
  ```
138
 
139
+ Tokenization: `tokenizer.json` is a standard BPE vocab (8192 tokens,
140
+ byte-level). It is **not** a HuggingFace `PreTrainedTokenizerFast` file — load
141
+ the `model.vocab` mapping directly (see `model.py` for the decode helper).
142
 
143
+ ## Training
 
 
 
 
 
144
 
145
+ - **Data:** ~94M tokens of TinyStories (byte-level BPE, 8192 vocab).
146
+ - **Hardware:** CPU-only (32 cores, no GPU). ~5000 steps, batch 32×512.
147
+ - **Schedule:** linear warmup (200) → cosine decay, peak 3e-4, min 3e-5.
148
+ - **Checkpoint:** best validation perplexity (val ppl ~15.6 on 2M held-out
149
+ tokens).
150
+ - **Reproducibility:** seed 42. The training script is available on request;
151
+ this repo ships the architecture (`model.py`) and weights only.
152
 
153
+ ## Honest caveats
154
+
155
+ - Trained on CPU; throughput is a hardware artifact, not a model property, so
156
+ I am not reporting tokens/sec.
157
+ - The model is small on purpose. Treat it as a reference implementation of a
158
+ clean GQA+SwiGLU+RoPE+RMSNorm subword GPT at the ~5M scale, not as a
159
+ competitive language model.
160
+ - Sampling quality is the weak spot; use greedy for coherent output.