Personalize this lesson
Adapt explanations and teaching visuals to your background and preferred voice.
The last chapter asked how a trained model spends compute while emitting tokens: greedy, beam, or sampling. Before serving, someone has to make a different allocation: with a fixed training-FLOP budget, how many parameters and training tokens should the run use?
For a code assistant, choose between two runs. One candidate spends the budget on a huge model trained on a modest corpus of source code, issues, and documentation. Another uses a smaller model and feeds it far more data. Predict which one wins before seeing a curve: too little capacity leaves patterns unrepresented, while too little data leaves capacity underused. Either mistake can turn a large training bill into a weaker assistant.
Scaling laws turn that choice into an empirical forecast. In pre-training studies, the usual quality metric is cross-entropy loss, or how surprised the model is by the next token.
Kaplan et al. at OpenAI [1] measured influential transformer curves. Hoffmann et al. at DeepMind later found a more balanced split of model size and data for compute-optimal dense training, often called Chinchilla scaling.[2]
Neither fit travels unchanged across objectives, data, architectures, or measurement choices.
Three symbols keep the budget legible:
- Parameters () are learnable weights. They give a model room to store and compose patterns. Papers count differently, so check whether embeddings and the final unembedding head are included before comparing ratios.
- Training tokens () are the subword pieces shown during training. They are opportunities to update those weights, not a direct measure of unique knowledge.
- Compute () is training work measured in floating-point operations (FLOPs). For a dense transformer, a first planning estimate is : about FLOPs per token for a forward pass and for backpropagation. Kaplan used this accounting, while later work counted layer and output costs more carefully.[1][2] Use it for sizing, then profile the actual architecture.
Check units before trusting any ratio. A 1B-parameter dense model trained on 20B tokens gives approximately 6 × 10^9 × 20 × 10^9 = 1.2 × 10^20 training FLOPs. Doubling both quantities makes that estimate four times larger, even though each one only doubled.
Double parameters, double data, or both
Start with four runs on the same held-out set. A 1-billion-parameter model sees 10 billion tokens, then three follow-up runs change one resource at a time or both together. Before reading the losses, predict which single-axis change will help more, and whether changing both can beat either change alone.
| Experiment | Parameters | Tokens | What changed | Approximate loss |
|---|---|---|---|---|
| Baseline | 1B | 10B | Nothing | 2.80 |
| Double model size | 2B | 10B | 2x parameters | 2.60 |
| Double data | 1B | 20B | 2x tokens | 2.55 |
| Double both | 2B | 20B | 2x each | 2.35 |
These rows are a synthetic fixture, not a measurement or the later fitting law. They make the bottlenecks visible: either resource helps, but both together lower loss more than either single change. The gains still taper. A 10x increase in parameters doesn't cut loss by 10x; it multiplies the relevant loss term by a smaller, repeatable factor.
That repeatable factor is the useful part of a power law. On a log-log plot, an idealized power-law term becomes a straight line, so a handful of measured runs can estimate how loss changes with parameters, data, or compute. The forecast answers a planning question such as, "If compute grows 10x, what scale should we try?" It doesn't replace a target-scale run, and later we add a loss floor and let parameters and data interact.

Use the fitted parameter exponent to inspect those diminishing returns. This script changes only the parameter-limited term, so its percentages stop short of total loss.
1alpha_n = 0.076
2
3for parameter_multiplier in [2, 10, 100]:
4 scaled_term = parameter_multiplier ** (-alpha_n)
5 reduction = 1 - scaled_term
6 print(
7 f"{parameter_multiplier:>3}x parameters -> "
8 f"{scaled_term:.3f}x parameter-limited loss term "
9 f"({reduction:.1%} reduction)"
10 )12x parameters -> 0.949x parameter-limited loss term (5.1% reduction)
2 10x parameters -> 0.839x parameter-limited loss term (16.1% reduction)
3100x parameters -> 0.705x parameter-limited loss term (29.5% reduction)Your team can either double parameters from 1B to 2B while keeping data at 10B tokens, or keep 1B parameters and double data to 20B tokens. Which option gives lower loss in the table?
Answer
Doubling data gives lower loss in this synthetic table: 2.55 instead of 2.60. Data doesn't always win; parameters and tokens are separate bottlenecks, and scaling studies tell you which one is binding for a budget.
Kaplan scaling laws (2020)
The synthetic runs show why one resource can't stand in for the other. Kaplan's 2020 study [1] measured each bottleneck separately for transformer language models. Read the three fits as conditional statements: hold the other resources far enough away, then ask how loss changes.
The three power laws
1. Scaling with parameters (model size )
Suppose data is plentiful and the model is the limiting resource. If you double , should the parameter-limited part of loss fall by half, stay fixed, or move by a smaller factor? The fitted curve answers that question:
Here the parameter-limited term shrinks by a fixed multiplier when is multiplied. With , multiplying parameters by 10 reduces that term by about 16%, not total loss by 16%. Total loss can still be held up by a data term or a floor, which is why this single-variable fit isn't a complete training plan.
2. Scaling with data (dataset size in tokens)
Now reverse the bottleneck. If the model is already large enough, should another 10x tokens reduce the data-limited term by 10x or by a smaller factor?
Hold model size large enough that data is the bottleneck. More training tokens then lower loss along a predictable curve with . The exponent describes the slope of this regime, not a promise that any new token source has the same value.
3. Scaling with compute-optimal training compute ()
Finally, allocate both resources together. If compute is spent efficiently, how should the best achievable loss change as the budget grows?
This third curve uses , the estimated minimum compute needed to reach a loss when compute is allocated efficiently. It isn't the curve for an arbitrary run with a poor model/data split. Kaplan's fitted exponent is under the dense-transformer accounting. Actual work also includes attention kernels, optimizer overhead, activation recomputation, sequence length, and architecture choices such as MoE sparsity.
The three slopes don't tell you to compare and and pick the larger one. They describe different controlled regimes. To choose and together, put them on one fixed-compute frontier. Kaplan's frontier favored much larger models and relatively little data.
Kaplan's compute-optimal frontier favored larger models
Under Kaplan's fitted regime, extra compute went mostly into model size, with a smaller share going to new data. That recommendation came from the joint frontier, where a relative increase in parameters moved the best achievable loss more than the same relative increase in data.
GPT-3 made that strategy visible: 175B trainable parameters and 300B training tokens, or about 1.7 tokens per parameter.[3] The ratio describes what GPT-3 used; it doesn't prove that the ratio was optimal for another corpus or objective.
The compute-optimal frontier
Now hold total compute fixed and move along the choices that spend it efficiently. Kaplan reported:
The question to test is simple: with 10x more compute, does the fitted plan grow and at the same rate? The answer is no. These exponents come from loss as a function of model size and training steps, not from comparing and as standalone power laws. Kaplan also fit a joint early-stopped loss surface:
That form describes overfitting when data is scarce. It isn't the derivation of the / allocation. In that frontier, 10x more compute means about 5.4x more parameters but only 1.9x more tokens. Chinchilla later re-fit the allocation and found a much more balanced / result.
The small script turns those exponents into multipliers. It evaluates the fitted arithmetic only, so its output isn't a hardware benchmark or a claim about wall-clock speed.
1frontiers = {
2 "Kaplan": (0.73, 0.27),
3 "Chinchilla": (0.50, 0.50),
4}
5
6for compute_multiplier in [10, 100]:
7 print(f"{compute_multiplier}x training compute")
8 for name, (parameter_exp, token_exp) in frontiers.items():
9 parameters = compute_multiplier ** parameter_exp
10 tokens = compute_multiplier ** token_exp
11 print(f" {name:<10} N={parameters:5.2f}x, D={tokens:5.2f}x")110x training compute
2 Kaplan N= 5.37x, D= 1.86x
3 Chinchilla N= 3.16x, D= 3.16x
4100x training compute
5 Kaplan N=28.84x, D= 3.47x
6 Chinchilla N=10.00x, D=10.00x
Why did Kaplan-era scaling produce parameter-heavy models?
Answer
Kaplan's fitted compute-optimal frontier said that, for a fixed training compute budget, loss improved most by growing parameters much faster than tokens. That didn't come from comparing the single-variable exponents and directly. It came from Kaplan's compute-efficient fits of loss versus model size and training steps, reported as and .
Use the dense proxy to compare two published parameter-token configurations. The values expose the accounting; rounded counts and architecture-aware FLOPs still differ.
1def dense_training_flops(parameters, tokens):
2 return 6 * parameters * tokens
3
4gpt3_style = dense_training_flops(175e9, 300e9)
5small_data_rich = dense_training_flops(70e9, 1.4e12)
6
7print(f"GPT-3-style training FLOPs: {gpt3_style:.2e}")
8print(f"70B / 1.4T-token training FLOPs: {small_data_rich:.2e}")1GPT-3-style training FLOPs: 3.15e+23
270B / 1.4T-token training FLOPs: 5.88e+23The Chinchilla reallocation (2022)
Kaplan's frontier made a sharp prediction: with one fixed compute budget, a large model trained briefly should beat a smaller model trained longer. Chinchilla asked whether that prediction survived when data and model size were varied together. Before reading the result, choose the likely winner for a code assistant whose corpus still contains useful, unseen examples.
Hoffmann et al. at DeepMind [2] trained over 400 models, from 70M to more than 16B parameters and from 5B to 500B tokens. Across three fitting approaches, they found that Kaplan's allocation had undervalued data.
Their predicted 70B Chinchilla run used the same reported training compute as 280B Gopher while seeing four times as many tokens.
The disagreement wasn't evidence for two incompatible kinds of transformer. Porian et al. [4] reproduced Kaplan-style experiments and isolated three setup differences: Kaplan omitted the final decoding-layer computation, used a fixed warmup that was too long for small models, and didn't tune optimizer settings as scale changed.
After those corrections, their fitted frontier moved close to Chinchilla's. They also found that careful learning-rate decay wasn't the central explanation Hoffmann et al. had proposed. Compute accounting and fitting choices can move an exponent before any architecture changes.
Chinchilla-optimal training
Hoffmann et al. report three fitting approaches, not one magic exponent. Each route asks where loss is lowest while keeping training FLOPs fixed:
| Approach | What they fit | ||
|---|---|---|---|
| 1. Envelope of training curves | Lowest loss along interpolated runs | ||
| 2. IsoFLOP profiles | Valley of final loss at fixed FLOPs | ||
| 3. Parametric loss | Closed-form frontier from that surface |
The ~20 tokens-per-parameter rule tracks Approaches 1 and 2, and it's the ratio used for the 70B Chinchilla run on 1.4T tokens. The number belongs to Approach 3's parametric frontier, not to a separate 20:1 recipe. Keeping those outputs distinct prevents a fitting detail from turning into a false constant.
For planning, the common result is easier to remember: under this fixed training-compute objective, grow model size and data at roughly equal rates. Double compute, then start near the parameters and the tokens, before checking your own data and stack.
For Chinchilla-style compute-optimal training, how many tokens does a 70B dense model need?
Answer
Use approximately 20 tokens per parameter: tokens. This is a fitted rule of thumb for the dense-transformer setup Hoffmann et al. studied, not a universal constant.
Treat 20:1 as a candidate starting point, not a constant.[2] Proxy runs on your corpus tell you whether data or capacity is binding before you commit to a larger run.
The next function does that first-pass arithmetic. It takes a dense training-FLOP budget, substitutes into , and returns a starting value for and .
1def chinchilla_style_size(training_flops, tokens_per_parameter=20):
2 parameters = (training_flops / (6 * tokens_per_parameter)) ** 0.5
3 tokens = tokens_per_parameter * parameters
4 return parameters, tokens
5
6parameters, tokens = chinchilla_style_size(1e24)
7print(f"Parameters at 1e24 FLOPs: {parameters / 1e9:.1f}B")
8print(f"Tokens at 20:1: {tokens / 1e12:.2f}T")1Parameters at 1e24 FLOPs: 91.3B
2Tokens at 20:1: 1.83T
Chinchilla vs. Gopher: a concrete example
The Gopher comparison makes the reallocation concrete. Both rows below use the paper's reported training budget, but they spend it in opposite ways:
| Model | Parameters | Training Tokens | Ratio (D/N) | Compute (FLOPs) |
|---|---|---|---|---|
| Gopher | 280B | 300B | 1.07:1 | 5.76 × 10²³ |
| Chinchilla | ~70B | 1.4T | 20:1 | 5.76 × 10²³ |
The FLOP column is the matched budget reported by Hoffmann et al. It won't equal exactly when you multiply the rounded counts: is a planning approximation, while the paper uses architecture-aware accounting.[2]
On the paper's reported downstream evaluations, Chinchilla beat Gopher despite using one quarter as many parameters and about 4.7x as many tokens. The source also reports lower inference cost and memory for the smaller model.[2] That comparison is bounded by its setup: the models were trained with the paper's TPUv3/TPUv4 and JAX/Haiku stack, and quality came from stated benchmark protocols. It isn't a measured serving-throughput or dollar comparison for your hardware.
Why was Chinchilla also a serving-cost breakthrough?
Answer
Chinchilla matched Gopher's reported training compute with a much smaller model trained on more tokens. It scored better on the reported evaluations, and its lower parameter count implies lower dense FLOPs per inference token under the same proxy. The paper's result isn't a promise about latency, utilization, or dollars on a different serving stack.
Later dense-model token ratios
Published model reports show token-to-parameter ratios, but a ratio alone can't tell you which objective selected it.
Meta reports 15.6T pre-training tokens for the Llama 3 flagship.[5] For 405B, that's about tokens per parameter, above Chinchilla's roughly 20:1 fit.
Meta's own IsoFLOP fit, using its data and a FLOP budget, suggested a 402B model on 16.55T tokens. The 405B / 15.6T run landed close to that forecast.[5] Those facts support a model-size choice under Meta's fitted training objective; they don't show that lifetime inference cost selected the flagship ratio.
The smaller Llama 3 models show overtraining more clearly. If each sees the same reported 15.6T-token corpus, 8B works out to about tokens per parameter and 70B to about . Meta reports that its smaller models were trained much longer than compute-optimal and performed better than compute-optimal models at the same inference budget.[5] Treat the ratios as published configurations, then ask whether extra training pays back under your demand forecast. Don't assume every size should sit at 20:1.
You want to train a 10B-parameter model at Chinchilla-style ratios. About how many tokens and FLOPs do you need?
Answer
Tokens: . Training compute: FLOPs. An estimate in that range captures the planning rule, not a measured cluster bill.
1def chinchilla_tokens(parameters, tokens_per_parameter=20):
2 return parameters * tokens_per_parameter
3
4def dense_training_flops(parameters, tokens):
5 return 6 * parameters * tokens
6
7parameters = 10e9
8tokens = chinchilla_tokens(parameters)
9flops = dense_training_flops(parameters, tokens)
10
11print(f"Chinchilla-style tokens for 10B parameters: {tokens:.2e}")
12print(f"Dense training FLOPs: {flops:.2e}")1Chinchilla-style tokens for 10B parameters: 2.00e+11
2Dense training FLOPs: 1.20e+22Beyond Chinchilla: inference-aware scaling
Chinchilla picks the lowest pre-training loss for a fixed training-compute budget. Deployment adds another bill. If two candidates reach the same quality bar, the smaller one requires fewer dense FLOPs per request under the same proxy, even if it consumed more training FLOPs before launch. Whether that saves money depends on serving stack and demand.
That changes the question from “How should one training budget be split?” to “Which model reaches this quality target at the lowest lifetime cost for this demand?” An inference-aware objective counts both the original training run and all future tokens processed while the model serves users.
The inference cost problem
A model that serves enough traffic can accumulate inference FLOPs that rival or exceed its original training run. Sardana et al. [6] extend a Chinchilla-style loss fit with that deployment demand.
Under their modeled demand of roughly 1B requests, the fitted objective favors smaller models trained longer. They also train 47 models, ranging from 150M to 6B parameters, at token-to-parameter ratios up to 10,000. Quality kept improving in that tested range, although the sweep wasn't complete for every size.[6]
This is evidence about their architecture, data, and loss proxy, not a universal serving rule.
Read the objective from left to right. Training costs scale with model size times data ( FLOPs). Inference costs scale with model size times all served tokens () for a dense decoder-only model. Once is large enough, extra training for a smaller model can be repaid by cheaper requests. Here:
Here means total input plus output tokens across the model's deployment lifetime. This is a FLOP proxy. It doesn't specify an accelerator, software stack, batch or sequence distribution, precision, kernel baseline, or correctness test, so it can't establish wall-clock latency, throughput, utilization, or dollars. Those need measurements from the serving stack.
What question does inference-aware scaling ask that Chinchilla doesn't?
Answer
Chinchilla asks how to minimize pre-training loss under a fixed training-compute budget. Inference-aware scaling asks which model minimizes total lifetime cost at a target quality, including both training FLOPs and all future served-token FLOPs.
Concrete break-even example
Suppose two candidates can reach the same pre-training loss . Predict before calculating: which candidate should win at low demand, and which one should win after enough requests? The numbers below are an arithmetic illustration, not two measured models from Sardana et al. A real comparison first has to show that both candidates hit the quality target.
- Model A (Chinchilla-style): 70B parameters trained on 1.4T tokens. Training cost ≈ FLOPs. Inference cost per token ≈ B FLOPs/token.
- Model B (inference-aware, smaller + over-trained): 30B parameters trained on ~4T tokens (heavier over-training to match quality). Training cost ≈ FLOPs (slightly higher upfront). Inference cost per token ≈ B FLOPs/token, less than half of Model A.
The break-even point is where Model B's extra training work has been repaid by its cheaper requests. Under the equal-quality assumption, Model A is cheaper below about 1.65T served tokens; Model B wins above it. This fixture has no hardware, framework, precision, batching, kernel baseline, or correctness measurement, so it demonstrates the accounting trade-off rather than a deployment speedup or dollar saving.

The script below computes the break-even point from the stated FLOP proxy. It measures arithmetic only, with neither model measurement nor equal-quality evidence.
1def train_flops(parameters, tokens):
2 return 6 * parameters * tokens
3
4def inference_flops(parameters, served_tokens):
5 return 2 * parameters * served_tokens
6
7model_a_train = train_flops(70e9, 1.4e12)
8model_b_train = train_flops(30e9, 4e12)
9extra_train = model_b_train - model_a_train
10savings_per_token = 2 * (70e9 - 30e9)
11break_even_tokens = extra_train / savings_per_token
12
13print(f"Model A training FLOPs: {model_a_train:.2e}")
14print(f"Model B training FLOPs: {model_b_train:.2e}")
15print(f"Break-even served tokens: {break_even_tokens:.2e}")1Model A training FLOPs: 5.88e+23
2Model B training FLOPs: 7.20e+23
3Break-even served tokens: 1.65e+12The first script finds the crossing algebraically. Now test both sides of that crossing with the same proxy: at 1T served tokens, training cost still dominates; at 3T, repeated serving makes the smaller model cheaper.
1def total_flops(parameters, training_tokens, served_tokens):
2 return 6 * parameters * training_tokens + 2 * parameters * served_tokens
3
4models = {
5 "70B / 1.4T": (70e9, 1.4e12),
6 "30B / 4.0T": (30e9, 4.0e12),
7}
8
9for demand in [1e12, 3e12]:
10 costs = {
11 name: total_flops(parameters, tokens, demand)
12 for name, (parameters, tokens) in models.items()
13 }
14 cheaper = min(costs, key=costs.get)
15 print(f"{demand / 1e12:.0f}T served tokens -> cheaper candidate: {cheaper}")11T served tokens -> cheaper candidate: 70B / 1.4T
23T served tokens -> cheaper candidate: 30B / 4.0TWhat the inference-aware objective predicts
The arithmetic example gives one crossover. Sardana et al.'s fitted objective generalizes the direction: as expected demand rises, the best point shifts toward fewer parameters and more pre-training tokens at a fixed modeled loss target. That's a prediction under an explicit loss model and demand estimate, not evidence that a particular released model used that objective.
For each candidate, state the quality target and the evidence you can actually measure:
| Planning input | What to evaluate |
|---|---|
| Training loss is the objective and deployment demand is excluded | Use a Chinchilla-style baseline fitted to your data and architecture. |
| Large forecasted lifetime demand | Benchmark a smaller, longer-trained candidate against the quality target and lifetime serving cost. |
| Candidate ratios far outside fitted data | Collect proxy evidence in that regime instead of extrapolating the original fit without checks. |
The exact optimum depends on the loss target, architecture, data distribution, inference forecast, and serving stack. Don't infer a training objective from a released model's token-to-parameter ratio alone.
Public-text supply as a planning constraint
More tokens help only while useful tokens are available. Chinchilla and inference-aware fits both assume a data supply that can grow with the planned run. Public human-generated text is finite, and the size of that stock is uncertain.
Villalobos et al. [7] estimate an effective public-human-text stock of roughly tokens after quality filtering and multi-epoch adjustments. Under their assumed dataset-growth trends, full utilization falls between 2026 and 2032, with a median projection of 2028.
Their assumed 5x over-training policy moves the intersection earlier. Those are scenario forecasts, not observations about the current stock, and the paper's estimate depends on how quality and repeated passes are counted.
Once the data regime changes, is no longer a safe extrapolation. A team may filter and deduplicate harder, reuse data across controlled epochs, transfer from another domain, or add synthetic data. Each choice can add signal, but each also changes what the fitted term means.
The next calculation compares one reported dataset with the projected stock. It measures dataset size only, not unique-text consumption or model quality.
1effective_stock = 4e14 # Villalobos et al.: ~400T effective stock at utilization
2llama3_405b_tokens = 15.6e12
3chinchilla_style_tokens = 20 * 405e9
4
5print(f"Llama 3 405B reported tokens: {llama3_405b_tokens / 1e12:.1f}T")
6print(f"Chinchilla-style 405B tokens: {chinchilla_style_tokens / 1e12:.1f}T")
7print(
8 "Reported Llama 3 dataset / projected effective stock: "
9 f"{llama3_405b_tokens / effective_stock:.1%}"
10)
11print("Comparison is dataset size, not unique-text consumption.")1Llama 3 405B reported tokens: 15.6T
2Chinchilla-style 405B tokens: 8.1T
3Reported Llama 3 dataset / projected effective stock: 3.9%
4Comparison is dataset size, not unique-text consumption.In the Villalobos et al. forecast, why does assumed over-training move full utilization earlier?
Answer
A longer-trained model uses a larger token budget per parameter than a Chinchilla-style baseline. Under a fixed effective-stock estimate and continued growth assumptions, larger dataset requirements intersect the projected stock earlier. This is a property of the scenario, not proof that an exhaustion date has occurred.
A new scaling axis: test-time compute
Training scale fixes the weights. Serving still gives you a per-query knob: how much work should the model spend before returning one answer?
A system can generate a longer trace, sample several candidates, or search with a verifier. Snell et al. [8] study those revision and verifier-search strategies in a FLOP-matched evaluation on MATH.
When a smaller base model already solves some items, adaptively allocated test-time compute can beat a roughly 14x larger pretrained model on easier and intermediate items. Harder items favor more pre-training in their comparison. Read that finding as task- and method-specific quality evidence under a stated FLOP budget, not as latency or throughput on a production engine.
DeepSeek-R1 is a related post-training example, not a replacement for pre-training scale. R1-Zero uses reinforcement learning without supervised fine-tuning first; the final R1 pipeline adds cold-start data, supervised fine-tuning, and further RL stages.[9] Post-training can change how many tokens a deployed model spends per query. It doesn't mean pre-training data or compute stopped mattering.
For sizing, this adds a second trade-off. At one quality target, you might choose a larger or longer-trained model that answers in one pass, or a smaller model that spends more compute on hard queries. More candidates and longer responses also multiply , so they feed back into the lifetime-cost objective.
The small calculation below isolates generated-token cost for sampled candidates. It has no accelerator, batching, precision, kernel baseline, or verifier, so its output shows linear FLOP accounting rather than a production performance result. A real request also includes prompt tokens and any verifier work.
1def generation_flops(parameters, output_tokens_per_candidate, candidates):
2 return 2 * parameters * output_tokens_per_candidate * candidates
3
4parameters = 8e9
5output_tokens_per_candidate = 512
6for candidates in [1, 4, 16]:
7 flops = generation_flops(parameters, output_tokens_per_candidate, candidates)
8 print(f"{candidates:>2} candidate(s): {flops:.2e} generation FLOPs per request")11 candidate(s): 8.19e+12 generation FLOPs per request
2 4 candidate(s): 3.28e+13 generation FLOPs per request
316 candidate(s): 1.31e+14 generation FLOPs per requestWhy is test-time compute a separate scaling axis rather than just a larger fixed model?
Answer
Parameters and pre-training tokens are fixed once the model is trained. Test-time compute is chosen per query: the same deployed model can spend more generation or multiple sampled attempts on harder inputs. That creates an additional serving-cost trade-off, while the attainable quality gain still depends on the trained model and task.
When the shortcut breaks
Scaling laws become useful when you know what each shortcut leaves out. Five failure patterns are worth recognizing because each one points to a different experiment.
A ratio isn't a constant
Suppose a 1B model trained on 20B tokens performs poorly on a messy internal-code corpus. The tempting response is to memorize the ratio more firmly and scale the model, but 20:1 was fitted for a particular dense-transformer and general-web-text regime. Data quality, tokenizer design, optimizer settings, repetition, and architecture can move the useful ratio.
Start with 20:1 as a baseline, then run 100M to 1B proxy models on the actual corpus. Fit the trend you observe. That small experiment tells you whether data or capacity is binding before you scale either one by orders of magnitude.
FLOP estimates aren't cluster bills
If a spreadsheet gives two runs the same but the cluster bills differ, the estimate did its job as a first check and then reached its limit. The dense rule leaves out attention-kernel details, optimizer state, activation checkpointing, sequence length, utilization, distributed communication, data-pipeline stalls, and sparse routing.
Replace the proxy with measurements from your stack before committing budget: accelerator model and count, framework and kernel versions, token and sequence shapes, batch and concurrency, precision, exact baseline implementation, and a correctness check. Then report wall-clock throughput or dollars per token with those conditions attached. A bare “2x faster” is not evidence another team can reproduce.
Low loss isn't deployed capability
An excellent cross-entropy forecast can still lead to a coding assistant that hallucinates APIs, ignores instructions, or fails safety checks. The curve predicts next-token compression on a training distribution. It doesn't directly measure factuality, downstream tasks, instruction following, alignment, or reasoning.
Reserve budget for instruction tuning, evaluation, and alignment. Instruction tuning and RLHF [10] can change behaviors that the pre-training loss curve never observes. Keep those checks in the plan even when the loss forecast looks smooth.
Training-optimal isn't lifetime-optimal
A 70B Chinchilla-style model can be the right answer for a training-loss objective and the wrong answer for a heavily used service. Chinchilla spends less upfront compute than a longer-trained small model, while the small model spends fewer FLOPs on every request under the dense proxy.
Estimate served-token demand before choosing a size. Compare across candidates that meet a measured quality target, then validate the crossover on the actual serving stack. The formula predicts a direction; it doesn't supply a latency, utilization, or dollar number by itself.
Extrapolation needs a middle rung
A clean line through 100M to 1B proxy runs can still miss badly at 100B. Outside the measured range, optimizer instability, numerical precision, data exhaustion, or distributed communication can introduce a new bottleneck.
Run at least one mid-scale validation before booking the full target. For a 100M to 1B proxy range and a 100B target, a 10B run is a useful check. Treat the extrapolation as a hypothesis, and refit when measured loss leaves its forecast band.
Scaling law breakdowns and limitations
The curve can be smooth while its assumptions change underneath. Scaling laws are empirical fits, not physical laws: architecture, data quality, tokenizer, and optimizer regime can all move the exponents. Carry the measured range and objective with every forecast.
Emergent abilities
Wei et al. [11] highlighted tasks where measured performance stayed near zero and then jumped at larger scales, which looked like a phase transition. Schaeffer et al. [12] argued that many jumps came from the metric: replacing exact-match thresholds with continuous scores often made the same progress look smoother.
When a benchmark suddenly turns upward, inspect the scoring rule before inventing a new scaling law. Keep the thresholded task result if it matters to users, but pair it with a continuous metric that shows whether the underlying behavior changed gradually.
Task-specific ceilings
Downstream tasks introduce their own ceilings. When pre-training loss keeps falling but factuality, instruction-following, or safety metrics plateau, more pre-training alone isn't a fix. A coding assistant still needs data-quality checks, post-training, evaluation, and alignment after the pre-training budget is chosen. Instruction tuning and RLHF [10] belong in that later budget; they aren't a free byproduct of a lower .
Why can a scaling study predict great loss but still produce a bad coding assistant?
Answer
Scaling laws predict pre-training loss, not factual accuracy, instruction following, domain reliability, or safety behavior. A coding assistant still needs data-quality checks, post-training, evaluation, and alignment work after the pre-training budget is chosen.
Architecture sensitivity
Before applying a dense fit to another architecture, ask what means for both capacity and per-token work. That shortcut breaks for:
- Mixture-of-Experts (MoE) (lesson): MoE models activate only some parameters for each input, separating total parameter count from per-token compute. A dense fit can't tell you how those two quantities should scale together.
- State Space Models (SSMs): SSMs process sequences recurrently rather than with quadratic attention. Their exponents need independent measurements.
- Hybrid architectures: A model combining attention with SSMs or another mechanism needs a fresh fit for its combined capacity and compute paths.
Dense-transformer curves remain useful context, but they can't choose the allocation for these systems. Measure total and active parameters, data, compute, and quality on the architecture you plan to train.
Why can't you blindly apply dense-transformer scaling laws to MoE models?
Answer
Dense scaling laws treat parameter count as the main size variable. MoE models split total parameters from active parameters per token. Total parameters affect memory and routing; active parameters affect compute. That means you need a separate empirical scaling fit.
From theory to practice: running a scaling study
At this point, the question is operational: how do you turn a curve into a safe decision? A scaling study uses small, controlled proxy runs to forecast a larger run before anyone commits its full budget. The forecast earns trust in stages. If a mid-scale check leaves the forecast band, stop and refit instead of spending through the mismatch.

A complementary tool is µ-Transfer (Tensor Programs V) [13]. Under Maximal Update Parametrization (µP), many optimal hyperparameters stay stable as width changes, so a small proxy can tune settings for a larger target. Yang et al. test this on Transformer and ResNet experiments, transferring from 13M parameters to BERT-large and from 40M parameters to a 6.7B GPT-3 model while cutting tuning cost.
Those are results for the tested setups, not a reason to skip mid-scale validation. Hyperparameter transfer, the loss fit, the data mix, and the hardware stack can fail independently.
Fitting the parametric loss function
To see what a scaling study actually fits, use Chinchilla Approach 3 as a small worked surface:[2]
If both model capacity and data are finite, which penalties should remain in the measured loss?
As and grow, the two penalties shrink and the fitted floor is what remains in this measured regime. is the penalty for finite parameters, and is the penalty for finite training data. is an extrapolated fit parameter, not a measurement of language's irreducible entropy.
Before fitting noisy runs, practice reading a known surface. The table below is synthetic and was generated from
then rounded to three decimals. A real study would estimate all constants from noisy runs. Starting from a known law keeps this arithmetic inspectable.
| Parameters (N) | Tokens (D) | Observed loss |
|---|---|---|
| 100M | 1B | 2.895 |
| 100M | 5B | 2.745 |
| 100M | 20B | 2.634 |
| 500M | 1B | 2.813 |
| 500M | 5B | 2.663 |
| 500M | 20B | 2.552 |
| 1B | 5B | 2.631 |
| 1B | 20B | 2.520 |
| 1B | 100B | 2.408 |
Read across a row and down a column. More tokens lower loss when stays fixed; more parameters lower loss when stays fixed. The three-term formula captures both penalties at once, so a forecast must say which resource changed.

Now test whether a fit can recover its own generating law. The script holds out the 1B / 100B run, searches a coarse grid for and using the other eight points, and forecasts 70B / 1.4T. , , and stay fixed so the search fits on one screen. A real fit would estimate all five constants, report uncertainty, and still require a mid-scale check.
1def scaling_loss(n, d, e, a, alpha, b, beta):
2 return e + a / (n ** alpha) + b / (d ** beta)
3
4E, A, B = 1.10, 2.80, 7.80
5experiments = [
6 (1e8, 1e9, 2.895),
7 (1e8, 5e9, 2.745),
8 (1e8, 2e10, 2.634),
9 (5e8, 1e9, 2.813),
10 (5e8, 5e9, 2.663),
11 (5e8, 2e10, 2.552),
12 (1e9, 5e9, 2.631),
13 (1e9, 2e10, 2.520),
14 (1e9, 1e11, 2.408),
15]
16train, held = experiments[:-1], experiments[-1]
17
18def sum_squared_error(alpha, beta):
19 total = 0.0
20 for n, d, loss in train:
21 pred = scaling_loss(n, d, E, A, alpha, B, beta)
22 total += (pred - loss) ** 2
23 return total
24
25best_error = float("inf")
26best = (0.0, 0.0)
27for alpha_i in range(40, 121, 2):
28 for beta_i in range(40, 121, 2):
29 alpha = alpha_i / 1000
30 beta = beta_i / 1000
31 error = sum_squared_error(alpha, beta)
32 if error < best_error:
33 best_error = error
34 best = (alpha, beta)
35
36alpha_fit, beta_fit = best
37n_held, d_held, loss_held = held
38hold_pred = scaling_loss(n_held, d_held, E, A, alpha_fit, B, beta_fit)
39target = scaling_loss(70e9, 1.4e12, E, A, alpha_fit, B, beta_fit)
40
41print(f"Recovered alpha={alpha_fit:.3f}, beta={beta_fit:.3f}")
42print(
43 f"Hold-out 1B / 100B: pred={hold_pred:.3f}, "
44 f"observed={loss_held:.3f}, residual={hold_pred - loss_held:+.4f}"
45)
46print(f"Forecast 70B / 1.4T tokens: {target:.3f}")1Recovered alpha=0.070, beta=0.098
2Hold-out 1B / 100B: pred=2.408, observed=2.408, residual=+0.0002
3Forecast 70B / 1.4T tokens: 2.091The hold-out residual is tiny because the table came from the same law. Real runs add noise and setup drift. Compare the 70B forecast with a mid-scale run using the planned tokenizer, data mix, sequence length, and training stack; stop or refit when measured loss leaves the forecast band. A smooth extrapolation still has to earn the budget.
You fit a loss surface on 100M to 1B proxy runs and forecast 2.091 at 70B / 1.4T. What should you do before booking that run?
Answer
Keep a hold-out residual, then run a mid-scale check on the real tokenizer, mix, and stack. If measured loss leaves the forecast band, refit. Don't treat the 70B number as measured.