Antivision · Latent Rehearsal
15

What it costs
and what it delivers

Every earlier chapter compares our own rounds against each other. This one compares outward: GPT‑1, GPT‑2 and ours, on the only metric that is valid across different tokenizers, with the dollar price of each training run. The question is simple and uncomfortable: a model with fewer parameters, trained for less than a dollar, delivers what exactly?

Chapter 15 Prerequisite: 07 (scale and budget) and 08 (why PPL does not compare)

1 The comparison almost everyone gets wrong

The temptation is to say "our model has perplexity 31 and GPT‑2 has 29, so GPT‑2 is better". That means nothing. Perplexity is measured per token, and a token is not a universal unit: it is a choice made by the tokenizer. Our vocabulary has 16,392 entries trained on this corpus; GPT‑2's has 50,257, trained on English web text. The word "antevisão" may become two pieces in ours and six in GPT‑2's. Per-token perplexity compares two things counting different units — like comparing litres per kilometre with gallons per mile without converting.

The conversion exists and is old: bits per character. Sum the negative log-likelihood of every token in a text, convert from nats to bits, and divide by the number of characters — not tokens. The result answers a physical question: how many bits does this model need, on average, to transmit one character of this text? A character is the same thing for everybody. It is the metric of the compression literature, and the only honest one here.

This chapter's rule

No hand-picked text. The test text comes from the validation set itself (model/data/validacao.bin), decoded back into characters: blocks of 8,192 tokens that data preparation set aside before training and shuffled. No model of ours has seen them. Each block's domain — Portuguese, English or code — is decided by a counting rule written into the code (model/cost_vs_gpt2.py), not by judgement: structural code markers, Portuguese markers, and the rest is English.

2 Where our parameter saving actually is

Our largest model has the same body geometry as GPT‑2 small: 12 layers, 12 heads, 768 dimensions. The entire difference is the vocabulary, and it is not small.

Parameters, counted. "Embedding" is the table translating tokens into vectors, reused at the output (weight tying). "Body" is the transformer blocks — what actually computes. Our vocabulary: 16,392; GPT‑2's: 50,257; GPT‑1's: 40,478.
modeltotalembeddingbodyembedding as % of totallayers × d
mini7,410,4324,196,6083,213,82456.6%4 × 256
pequeno16,917,1206,294,91210,622,20837.2%6 × 384
medio34,092,5448,393,21625,699,32824.6%8 × 512
grande97,544,44812,589,82484,954,62412.9%12 × 768
GPT‑2 small124,439,80838,597,37685,054,46431.0%12 × 768
GPT‑1116,534,78431,087,10485,054,46426.7%12 × 768

The body is the same; the vocabulary is the weight. Our grande has 97.5 million parameters against GPT‑2 small's 124.4 — 21.6% fewer — and both have essentially the same body, 85 million. The 26.9 million of difference is almost entirely translation table: 50,257 entries against 16,392. That is not cleverness on our part, it is the consequence of training the tokenizer on this corpus instead of inheriting one. Chapter 01 measured the other side of the same coin: a vocabulary fitted to the corpus spends fewer tokens per character, so the same context window carries more text.

3 What the card changed

Every round so far was measured on CPU, and that is a choice of method: it is what lets anyone repeat the whole experiment without depending on a card. The price of that choice is time — 700 steps take 25 minutes. The same 700 steps on an RTX 5090 take 40 seconds. The difference is not comfort: it is what makes it possible to measure the whole ladder of sizes in one sitting, instead of over a weekend.

Tokens per second, measured on the machine itself, with batch 16, context 512 and accumulation 4 (grande with context 1024 and batch 8). The CPU is a Ryzen 7 5700X with 12 threads. The CPU figure for mini came from the duel round; the other three were measured later with the same training step as cloud/calibrate.py, but with a smaller batch to fit the machine's memory: batch 4 for pequeno and medio, batch 2 with context 1024 for grande. On CPU the batch barely changes throughput: mini measured the same way gave 3,841 tok/s with batch 16 and 4,108 with batch 4, a 7% difference.
modelCPU (tok/s)RTX 5090 (tok/s)how many times faster
mini≈ 3,800575,752151×
pequeno2,185509,073233×
medio1,203225,341187×
grande36198,725273×

The reading that matters is not "GPUs are fast", which everyone knows. It is the shape of the curve: from mini to pequeno the card barely loses speed (576k to 509k tokens per second) while the model's body triples. At those sizes the card is idle — the bottleneck is the small batch, not the arithmetic. Only from medio on does the curve behave as expected, falling with size. Training small models on a big card means paying for silicon that sits still, and the table below shows how much.

The CPU has no such idle regime: it slows with size from the first step (4,108, 2,185, 1,203, 361 tok/s). That is why the card's advantage grows with the model, from 151× on mini to 273× on grande. On this CPU, the 1.7 billion tokens Chinchilla asks for grande would take about 54 days; on the card, 4.8 hours.

4 Chinchilla's budget, and the corpus it demands

Chinchilla's rule (chapter 07) says efficient training uses about 20 tokens per parameter. Chapter 07 applied it to the body and not to the whole model, for the same reason as section 2: the embedding is a table, not compute capacity. Applied to our 309,083,117 training tokens:

Budget by size. "Epochs" is how many times the whole corpus would have to be repeated to reach the budget. Time and cost computed from section 3's measured speed and the real price paid for the machine, US$ 0.896 per hour.
modelbodybudget (20× body)corpus epochstime on the 5090cost
mini3.2 M64 M tokens0.211.9 minUS$ 0.03
pequeno10.6 M212 M tokens0.697.0 minUS$ 0.10
medio25.7 M514 M tokens1.6638 minUS$ 0.57
grande85.0 M1.70 G tokens5.504.8 hUS$ 4.28

We do not have the corpus for the large model, and that is the result, not an obstacle to hide. Training 85 million body parameters to Chinchilla's optimum would ask for 1.7 billion tokens; the corpus has 309 million. That would be five and a half epochs over the same text. Past that, the model memorises instead of generalising, and validation loss stops following training loss. medio already asks for 1.66 epochs — it sits at the edge of what the corpus sustains. This collection's practical conclusion is recorded here: from about 34 million parameters on, our limit stopped being the card and became the corpus. More GPU buys no more quality; more text does.

5 The ladder, measured

The first two rungs, trained on the full corpus with section 4's budget. The cells fill when each round closes.

Round escala: full corpus, batch 16 × context 512 × accumulation 4, Chinchilla budget over the body. Cost = real training time × US$ 0.896/h.
modelstepstokens seenvalidation lossPPLtimecost
duel control (mini, 60 M tokens)7005.7 M5.2577192.040 sUS$ 0.010
mini1,96164 M3.750342.51 min 25 sUS$ 0.021
pequeno6,483212 M2.861117.57 min 06 sUS$ 0.106

The budget matters more than the size. The same mini, same architecture and same 7.4 million parameters, goes from perplexity 192 to 42.5 — four and a half times better — purely by seeing 64 million tokens instead of the duel round's 5.7 million. Not one line of the model changed: what changed is how much it read. This collection's whole queue, chapters 03 to 14, ran on 5.7 million tokens per round, because that is what the CPU allowed in twenty minutes. That does not invalidate the comparisons between rounds, which remain fair against each other, but it places all of them in a short-training regime that the card has just shown to be well below what the corpus allows.

The next rung confirms the direction: pequeno, with 2.3× the parameters and 3.3× the tokens, reaches perplexity 17.5 for ten cents. The two runs together cost US$ 0.13 and took eight and a half minutes. That is the number that sets the scale for the rest of this chapter: if eight minutes and thirteen cents buy a jump from 192 to 17.5, what limits us is no longer the money or the card.

Chapter 13 §4's question — "how much does the world model cost the generator?" — asked at both budgets, with the recipe that did best there (level-2 hierarchy with the EMA teacher's target). Mean of three seeds (1337, 2 and 3) and the spread between them, best checkpoint of each round. The first version of this table had only seed 1337 on the ladder. "Fixed validation" is the new ruler (--eval-seed), where every evaluation reads the same batches; numbers from different rulers do not compare with each other. Chapter 19 tells the whole measurement.
budgetgenerator only+ world model (EMA)what the map costs
duel, mini — 5.7 M tokens, drawn validation5.2744 ± 0.04435.3351 ± 0.0455+1.15%
ladder, mini — 64 M tokens, seed 1337 only3.75033.6236−3.38%
ladder, mini — 64 M tokens, three seeds, drawn validation3.6452 ± 0.09253.6870 ± 0.0959+1.15%
ladder, mini — three seeds, fixed validation3.6367 ± 0.03183.7011 ± 0.0154+1.77%
ladder, pequeno — 212 M tokens, two seeds, fixed validation2.9477 ± 0.00023.0927 ± 0.0073+4.92%

The first version of this section read the table's second row as an inversion: with eleven times more tokens, the world model would stop costing and start paying 3.38%. The data did not confirm that reading. On seeds 2 and 3 the map went back to costing (+1.79% and +5.22%), and the −3.38% was a favourable seed, under a protocol where the drawn validation swung more than the effect itself.

With fixed validation, which chapter 19 explains, the ruler became clean: the seed spread fell to 0.87% of the loss on mini and to almost zero on pequeno. Under that ruler, the world model costs on every seed of both sizes: +1.77% on mini and +4.92% on pequeno. The cost does not vanish with more budget; it grows with the size of the model.

What stays from this section

The world model with hierarchy and EMA target costs the generator at every budget measured: about 1% on the duel, 1.77% on the ladder's mini and 4.92% on pequeno. The collection's sentences about the map's cost, measured on 5.7 million tokens, still hold at 64 and 212 million. What the map delivers in return — the heading, violation of expectation, the guardrail — is in chapters 12 and 13, and does not show up in validation loss. Chapter 19 tells how a single-seed reading ended up in a chapter, and what it changed in the method: training gained --eval-seed, and ladder rounds run with fixed validation.

6 Bits per character: us, GPT‑1 and GPT‑2

This chapter's central table. Lower is better. The three domain columns exist because the average hides what matters: a model can do well on Portuguese and badly on English, and reporting only the average would be picking the number that flatters.

Bits per character on the decoded validation set, by domain. Same text for every model; each uses its own tokenizer, which is exactly the point of the metric.
modelparameterstraining costbits/char (mean)PortugueseEnglishcode
pequeno (ours)16,917,120US$ 0.1061.2731.3601.4860.972
mini (ours)7,410,432US$ 0.0211.6371.7371.8211.354
GPT‑2 small124,439,808—1.7102.6281.1051.398
GPT‑1116,534,784—2.1523.0551.3962.006
How to read, decided before seeing the number

The expected result is not "ours does better". It is ours does better on Portuguese and code, GPT‑2 does better on English — for a reason with nothing mysterious about it: GPT‑2 was trained on English web text and never saw structured Portuguese, while 39% of our corpus is Portuguese Wikipedia and 33% is Python code. If ours also does better on English, the likeliest explanation is not that our model is better, but that the English test text is too easy or too short — and the table must be redone with more blocks before any celebration. A result that flatters whoever measured it deserves more suspicion than one that contradicts them.

The sanity check, run alongside and printed alongside: a paragraph of ordinary English from distributed-system documentation. Any model trained on web text must land between 1.0 and 1.5 bits per character here. This row exists to catch measurement error, and it caught one.
modelbits/char on plain Englishreading
GPT‑2 small1.121within expectation
GPT‑11.327within expectation
pequeno (ours)1.449within expectation
mini (ours)1.564at the upper edge
The error this row caught

The first version of this table gave GPT‑2 4.772 bits per character — four times the real value — and our pequeno 1.273. It was too good, and this section's "how to read" box, written before any number existed, said to distrust exactly that. The error was in the measurement, not the model: models from the transformers library shift the labels themselves, and the script was passing labels already shifted. GPT‑2 was being asked to predict two tokens ahead. The sanity row now runs always, and any value above 2.5 is flagged as suspicious in the program's own output.

The result is what the box predicted, with no favourable surprise. Ours does better on Portuguese by a wide margin — 1.360 against GPT‑2's 2.628, nearly double — and on code, 0.972 against 1.398. GPT‑2 does better on English, 1.105 against 1.486, and the explanation holds no mystery: it was trained on English web text, and only 14% of our corpus is English web. Each model does best on what it read.

The number that matters for this collection's thesis is in the first row. pequeno, with 16.9 million parameters against 124.4 — seven and a half times fewer — and ten cents of training, lands at 1.273 bits per character against GPT‑2's 1.710: 26% better across the three domains. And mini, with 7.4 million parameters and two cents, already passes GPT‑2 on the mean (1.637 against 1.710), losing only on English. This does not say we trained better than OpenAI did in 2019; it says a small model trained on its own domain outperforms, in that domain, a model seventeen times larger that was trained for another. It is an argument about data, not about cleverness, it says nothing against GPT‑2 on the English it was built for, and it is section 4's argument seen from the other side.

GPT‑1 trails on everything, including the English where it should be at home (1.396 against GPT‑2's 1.105). Both have the same 85-million-parameter body; what separates them is how much text was read and how big the vocabulary is. It is our ladder's lesson, measured one generation apart.

7 What Antivision adds

Bits per character measures one thing: predicting the next piece of text. It is the task GPT‑2 was built for, and comparing only on it is comparing on its home ground. The pieces this collection built do not show up in that metric, and that is precisely why they exist.

The functions the Antivision architecture adds, with each one's measured cost and the chapter where it was tested. "Cost to the generator" is how much validation loss worsens relative to the same model without the piece.
functionwhat it doescost to the generatorwhere measured
world modelpredicts the next latent state, not the next token: gives the planner a map to imagine with before writing+0.45% (EMA target)13 §4
energy rudderpicks the token that moves closest to a declared heading, searching in latent space0 (inference only)12, 13 §4
guardrail on the imagined stateblocks what the model is about to write, not what it already wrote: 0.0% digits on 4 of 4 maps0 (inference only)13 §5
dependency energydetects order violation without being given the token: +130% to +142% against +38% for plain error0 (inference only)13 §11
consulted memorya bank of abstract states read by attention, persisted to disk with a quantised index+9.73% (indistinguishable from the map without it)14
calibrated surprisemeasures when the map was wrong, and hands control back to the policy on those steps0 (inference only)13 §11

The sum is this collection's argument: the functions cost 0.45% of loss and no extra parameters on the generation path, because almost all of them live in inference. These functions need a world model. One can be added to an already trained model such as GPT‑2, but it costs more — chapter 13 measured that a second-stage map over a frozen encoder comes out more expensive than training it jointly.

Open questions