Chapter 8 · Section 8.8 · 50 min

Initialization and training stability

PaLM's 540-billion-parameter run had a problem its authors could not fully explain. About 20 times during training, despite gradient clipping, the loss suddenly jumped, sometimes by a lot, at irregular intervals and often late in training. Their fix was blunt. Rewind to a checkpoint about 100 steps before the spike, skip roughly 200 to 500 batches of data, and continue. The spike did not come back. And when they replayed exactly those skipped batches starting from a different checkpoint, there was no spike either (Chowdhery et al. 2022). So the data alone was not to blame. The spikes came from the combination of particular batches with a particular state of the model and the optimizer.

OPT-175B's public logbook tells a similar story, with loss divergences handled by lowering the learning rate and restarting from earlier checkpoints, and gradient clipping tightened from 1.0 to 0.3 along the way (Zhang et al. 2022). Every lab that trains large models has a version of this experience. This section collects what is now understood about why large runs become unstable and the fixes that labs actually use, z-loss, QK-norm, logit soft-capping, clipping, embedding scaling, rewinding, and the signals to watch so you see trouble coming. The deep-Transformer mechanisms (residual scaling, attention entropy collapse, warmup) are in §5.7. Here we focus on what goes wrong during a long run, and on the knobs a pretraining recipe turns.

What a loss spike is, and where spikes come from

A loss spike is a sudden rise in training loss, usually with a jump in the gradient norm, that either recovers within tens to thousands of steps or turns into divergence, where the loss climbs and never comes back. Recoverable spikes still cost compute and can leave lasting damage. Divergence ends the run unless you rewind.

Wortsman et al. (2023) made an important methodological point. Many instabilities seen in huge runs can be reproduced in small models trained at high learning rates, so they can be studied cheaply, and the fixes found at small scale transfer. Their study, together with the reports of PaLM, OPT, OLMo, and others, suggests a short list of causes.

causewhat you seefirst fixes
attention logit growthmax attention logits climb, attention entropy of some heads falls toward 0, then a spikeQK-norm, logit soft-capping, lower learning rate on WQ\mathbf{W}_Q, WK\mathbf{W}_K
output logit divergencethe output normalizer log⁡Z\log Z drifts far from 0, precision of the softmax degradesz-loss, weight decay, output soft-capping
a stale or tiny Adam second momentgradient norm jumps, update size jumps far above its usual RMSβ2=0.95\beta_2 = 0.95, smaller ϵ\epsilon, gradient clipping, skip the batch (§8.6)
a bad stretch of dataspikes at the same data position across runs, repeated or garbage documentsfilter the data, skip the batches, deduplicate
low-precision overflowinf or NaN in activations or gradientskeep reductions in fp32, loss scaling for fp16 (§8.5)
hardware faultssudden NaN, a loss jump uncorrelated with anythingchecksums, rerun the step on other hardware, rewind

The data row deserves a real example. OLMo 2's team traced many of their spikes to documents containing long runs of repeated nn-grams, such as a token repeated thousands of times, and removed every document with 32 or more consecutive repeats of an nn-gram of 1 to 13 tokens (Team OLMo 2024). Some spikes are data bugs.

The optimizer row is easy to see in a simulation. The widget below runs Adam on a noisy quadratic and injects a few "bad batches" whose gradients are many times larger than usual. With a long-memory second moment, the denominator v^\sqrt{\hat{\mathbf{v}}} cannot keep up with the sudden growth, the update becomes several times its usual size, and the loss spikes. The same batches with β2=0.95\beta_2 = 0.95, with gradient clipping, or skipped altogether, cause little or no spike.

Why do a few bad batches make Adam's loss spike, and what stops it?
Adam on a 64-dimensional noisy quadratic. At step 350, a few batches arrive with gradients many times larger than usual. Grey is the same run without the bad batches.
Loading interactive figure…

z-loss, a leash on the output normalizer

The cross-entropy of a softmax over a vocabulary of VV tokens, with logits z∈RV\mathbf{z} \in \R^V and target token yy, is

LCE=log⁡Z−zy,log⁡Z=log⁡∑v=1Vezv.\mathcal{L}_{\text{CE}} = \log Z - z_y, \qquad \log Z = \log\sum_{v=1}^{V}e^{z_v} .

Add the same constant cc to every logit, and log⁡Z\log Z grows by cc while zyz_y grows by cc, so the loss is unchanged. The overall level of the logits is a direction the loss cannot see. Its gradient confirms it. With p=softmax⁡(z)\mathbf{p} = \operatorname{softmax}(\mathbf{z}) and one-hot y\mathbf{y},

∂LCE∂z=p−y,1⊤(p−y)=1−1=0,\frac{\partial\mathcal{L}_{\text{CE}}}{\partial\mathbf{z}} = \mathbf{p} - \mathbf{y}, \qquad \mathbf{1}^\top(\mathbf{p} - \mathbf{y}) = 1 - 1 = 0,

so no gradient ever pushes the mean of the logits one way or the other. Yet the optimizer moves it anyway, because Adam rescales each coordinate separately and its updates do not preserve that zero sum, and because the logits are produced by shared weights that move for other reasons. Over a long run, log⁡Z\log Z drifts. That matters because large logits are imprecise in 16-bit arithmetic (bfloat16 has a spacing of 0.5 near 100, §8.5), and because large, drifting logits were associated with divergence in Wortsman et al.'s experiments.

z-loss, as used in PaLM (Chowdhery et al. 2022), adds a small penalty on the normalizer,

L=LCE+α(log⁡Z)2,α=10−4 in PaLM,\mathcal{L} = \mathcal{L}_{\text{CE}} + \alpha(\log Z)^2, \qquad \alpha = 10^{-4} \text{ in PaLM},

whose gradient follows from ∂log⁡Z/∂zv=pv\partial\log Z/\partial z_v = p_v,

∂∂z α(log⁡Z)2=2αlog⁡Z⋅p⟹∂L∂z=(1+2αlog⁡Z) p−y.\frac{\partial}{\partial\mathbf{z}}\,\alpha(\log Z)^2 = 2\alpha\log Z\cdot\mathbf{p} \quad\Longrightarrow\quad \frac{\partial\mathcal{L}}{\partial\mathbf{z}} = (1 + 2\alpha\log Z)\,\mathbf{p} - \mathbf{y} .

In plain words, z-loss scales the "push down" part of the gradient by 1+2αlog⁡Z1 + 2\alpha\log Z. Its component along 1\mathbf{1} is 1⊤(…)=2αlog⁡Z\mathbf{1}^\top(\ldots) = 2\alpha\log Z, the only force on the logits' overall level, and it always points back toward log⁡Z=0\log Z = 0. Since the cross-entropy is indifferent to the level, a model can satisfy z-loss at no cost in prediction quality, by learning to subtract a constant. Wortsman et al. confirmed that z-loss with α=10−4\alpha = 10^{-4} removes the output-logit divergence in their small-scale reproductions, and z-loss is part of the OLMo 2 recipe. The same idea keeps routers in mixture-of-experts models well behaved (the router z-loss of §13.3).

Python · cell 1

Without z-loss, log⁡Z\log Z settles wherever the optimizer happened to push it, here around 6.6. Increasing α\alpha pulls it toward zero, all the way to about 0.06 at α=0.1\alpha = 0.1, while the cross-entropy barely moves. (In this short run it rises slightly, from 1.654 to 1.713, because the optimizer spends some of its 800 steps on the shift. With a long run and the tiny α\alpha of real recipes, the cost is negligible.)

Interview

Cross-entropy with z-loss, and its gradient

Implement ce_zloss(logits, targets, alpha=1e-4) for logits of shape (N, V) and integer targets of shape (N,). Return (loss, dlogits), where loss is the mean over the batch of log⁡Z−zy+α(log⁡Z)2\log Z - z_y + \alpha(\log Z)^2 and dlogits is its gradient with respect to logits, of shape (N, V). Compute log⁡Z\log Z stably (it must not overflow for logits near 1,000).

Hidden tests, hints, and AI help, from $1.99 a month.

QK-norm, bounding the attention logits

The attention logit sij=qi⋅kj/dks_{ij} = \mathbf{q}_i\cdot\mathbf{k}_j/\sqrt{d_k}, for a head of width dkd_k with query qi=WQ⊤xi\mathbf{q}_i = \mathbf{W}_Q^\top\mathbf{x}_i and key kj=WK⊤xj\mathbf{k}_j = \mathbf{W}_K^\top\mathbf{x}_j, is bilinear in the weights, so if WQ\mathbf{W}_Q and WK\mathbf{W}_K each grow by a factor aa, the logits grow by a2a^2. Nothing in the loss stops that growth when a head wants to attend sharply, and once the logits are large, the softmax saturates, its Jacobian vanishes, and the head's gradients become erratic (§4.3, §5.7). Dehghani et al. (2023) hit exactly this while scaling vision Transformers. At around 8 billion parameters, the attention logits grew past 50,000 in magnitude within a couple of thousand steps, the attention weights became almost one-hot, and the loss diverged. Normalizing queries and keys removed the divergence, and their 22-billion-parameter ViT was trained with it from the start. Wortsman et al. reproduced the same growth in small language models at high learning rates.

QK-norm normalizes each head's query and key vectors before the dot product, usually with RMSNorm and a learned gain g\mathbf{g} (one per head dimension),

q^=gq⊙qRMS⁡(q),k^=gk⊙kRMS⁡(k),RMS⁡(x)=1dk∑mxm2+ε,\hat{\mathbf{q}} = \mathbf{g}_q\odot\frac{\mathbf{q}}{\operatorname{RMS}(\mathbf{q})}, \qquad \hat{\mathbf{k}} = \mathbf{g}_k\odot\frac{\mathbf{k}}{\operatorname{RMS}(\mathbf{k})}, \qquad \operatorname{RMS}(\mathbf{x}) = \sqrt{\tfrac{1}{d_k}\textstyle\sum_m x_m^2 + \varepsilon},

and then sij=q^i⋅k^j/dks_{ij} = \hat{\mathbf{q}}_i\cdot\hat{\mathbf{k}}_j/\sqrt{d_k}. A normalized vector has ∥q/RMS⁡(q)∥=dk\lVert\mathbf{q}/\operatorname{RMS}(\mathbf{q})\rVert = \sqrt{d_k} (ignoring ε\varepsilon), so by Cauchy-Schwarz, with gains bounded by gmax⁡g_{\max},

∣sij∣≤gmax⁡2 dk dkdk=gmax⁡2dk.|s_{ij}| \le \frac{g_{\max}^2\,\sqrt{d_k}\,\sqrt{d_k}}{\sqrt{d_k}} = g_{\max}^2\sqrt{d_k} .

In plain words, the logits can only grow as fast as the learned gains do, which is slowly and deliberately, instead of quadratically with every weight in WQ\mathbf{W}_Q and WK\mathbf{W}_K. With unit gains and dk=128d_k = 128, no logit can exceed about 11.3. QK-norm is now standard in many recent models, including OLMo 2, Qwen3, and Gemma 3 (which replaced Gemma 2's soft-capping with it). It is applied before rotary position embeddings, since RoPE rotates vectors without changing their norm (§5.5).

QK-norm is not always available. Multi-head latent attention, which compresses keys into a small shared latent to shrink the KV cache, never materializes each head's full key at inference time, so there is no key vector to normalize (§12.5 explains the design). Moonshot hit this with Kimi K2, a 1-trillion-parameter mixture of experts with MLA, trained with Muon (§8.6), and in their experiments its maximum attention logits kept growing until training became unstable. Their fix, QK-Clip, acts on the weights instead of the activations (Kimi Team 2025). After each optimizer step, for every head hh compute the largest attention logit Smax⁡hS^h_{\max} seen in the batch, a number the forward pass already has. If it exceeds a threshold τ\tau (they used 100), multiply that head's query and key projections by γh\sqrt{\gamma_h} each, with γh=τ/Smax⁡h\gamma_h = \tau/S^h_{\max}, so the head's logits shrink by exactly γh\gamma_h and its largest logit returns to τ\tau. Heads below the threshold are untouched, and so is the training step itself, since only the weights change after it. K2 was pretrained on 15.5 trillion tokens with no loss spikes, and the cap was active mainly early in training, after which the logits settled below it on their own.

Core

Attention scores with QK-norm

Implement qk_norm_scores(Q, K, g_q, g_k, eps=1e-6) for Q of shape (..., T_q, d_k) and K of shape (..., T_k, d_k), with gains of shape (d_k,). RMS-normalize every query and key vector over its last axis, multiply by its gain, and return the scaled scores Q^K^⊤/dk\hat{\mathbf{Q}}\hat{\mathbf{K}}^\top/\sqrt{d_k} of shape (..., T_q, T_k).

Hidden tests, hints, and AI help, from $1.99 a month.

Logit soft-capping

A blunter tool bounds the logits directly with a smooth saturating function. Gemma 2 replaced every attention logit and every final output logit zz by

softcap⁡c(z)=ctanh⁡(zc),ddzsoftcap⁡c(z)=1−tanh⁡2(zc),\operatorname{softcap}_c(z) = c\tanh\Big(\frac{z}{c}\Big), \qquad \frac{d}{dz}\operatorname{softcap}_c(z) = 1 - \tanh^2\Big(\frac{z}{c}\Big),

with c=50c = 50 for attention and c=30c = 30 for the final layer (Gemma Team 2024). In plain words, small logits pass through almost unchanged (since tanh⁡x≈x\tanh x \approx x near zero), and large ones are squashed smoothly toward ±c\pm c, so no logit can ever exceed cc. The derivative shows the price. For ∣z∣≫c|z| \gg c it goes to zero, so a capped logit stops receiving gradient, which is the point (it cannot keep growing) and also a risk (a head stuck at the cap learns slowly). Soft-capping needs care in fused attention kernels, since it changes the scores between the matrix product and the softmax, which is one reason later models moved to QK-norm.

Core

Soft-capping, forward and backward

Write softcap(z, c) returning ctanh⁡(z/c)c\tanh(z/c), and softcap_ce_grad(z, y, c) returning the gradient of the cross-entropy of softmax⁡(softcap⁡c(z))\operatorname{softmax}(\operatorname{softcap}_c(\mathbf{z})) with target index y, with respect to the raw logits z (a 1-D array). Use the chain rule. Do not use finite differences.

Hidden tests, hints, and AI help, from $1.99 a month.
methodwhat it boundscostused by
z-lossthe output normalizer log⁡Z\log Z (softly)one extra term in the lossPaLM, OLMo 2, many MoE routers
QK-normattention logits, by g2dkg^2\sqrt{d_k}two RMSNorms per headViT-22B, OLMo 2, Qwen3, Gemma 3
soft-cappingattention and output logits, hard ceiling cca tanh, complicates fused kernelsGemma 2
weight decayweight norms, hence logits indirectlynoneeveryone
QK-Clipeach head's largest attention logit, by rescaling WQ\mathbf{W}_Q, WK\mathbf{W}_K after a stepone max per head, already computedKimi K2 (with MLA and Muon)
lower learning rate for WQ\mathbf{W}_Q, WK\mathbf{W}_Kthe speed of logit growthnonead hoc fixes

Gradient clipping at scale

Nearly every large run clips the global gradient norm at 1.0, rescaling the whole gradient whenever ∥g∥>1\lVert\mathbf{g}\rVert > 1 (§0.6, §6.3). At scale, three facts about clipping are worth knowing.

It protects Adam's memory more than the step. §0.6 showed why an optimizer that normalizes its updates still needs clipping. A single huge gradient barely changes Adam's step on the spike itself, but it sits in v^\hat{\mathbf{v}} for many steps afterward, shrinking every later update of those coordinates, and with a long β2\beta_2 the first moment can also carry it past a lagging denominator, which is the mechanism of the simulator above. Clipping keeps the spike out of both moments.

If it is active on most steps, it is a hidden learning-rate change. A threshold that is always exceeded rescales every gradient, and with SGD that is just a smaller learning rate. Watch the fraction of steps that are clipped. Near the start of training it is often high, and later it should be rare.

Its threshold is not scale-free. The gradient norm depends on model size and on the loss scale, so 1.0 means different things for different models. OPT-175B tightened its clipping from 1.0 to 0.3 mid-run to tame instability, while DeepSeek-V3 and OLMo 2 kept 1.0.

Embedding scaling and initialization

Initialization choices that are invisible in small models matter at scale. Takase et al. (2023) analyzed spikes in pre-LN Transformers and identified two conditions that keep gradients well behaved, small sublayers (small initialization of each residual branch) and a large shortcut, meaning the residual stream itself, which starts as the embedding, should have entries of standard deviation near 1. With the common initialization of embeddings at standard deviation 0.02, the stream starts tiny, and the first layer norm divides by a tiny RMS, which amplifies gradients. Two fixes satisfy the condition. Multiply the embeddings by d\sqrt{d} (Vaswani et al. 2017 did this, and Gemma's code does too), or put a LayerNorm right after the embedding. Both prevented spikes in their experiments, which the authors present as verification of the analysis rather than as new methods.

Recipes differ in the details. OLMo 2 initializes every parameter from a normal distribution with standard deviation 0.02, DeepSeek-V3 uses 0.006, and many models scale the initialization of each residual branch's output projection by 1/2L1/\sqrt{2L} (§5.7). The general lesson holds across them. Pick the initialization so that activation and gradient scales are controlled at step zero, and check it by logging per-layer RMS for the first few hundred steps. Width-aware initialization rules that keep these scales fixed as models grow are the subject of §9.5.

Rewinding from a checkpoint

When a spike does not recover, the standard procedure is the one PaLM used.

  1. Rewind. Restore the model, optimizer state, scheduler step, and data loader position from a checkpoint safely before the spike, typically 100 or more steps earlier, so the state that led to the spike is gone.
  2. Skip data. Skip the batches around the spike, a few hundred in PaLM's case. This changes the combination of data and state that triggered it.
  3. Change something if it recurs. Lower the learning rate, tighten clipping, lower ϵ\epsilon, or reset Adam's second moment for the affected layers (Molybog et al. 2023).

This only works if the run can be rewound exactly. The data loader must be deterministic and resumable at any batch, checkpoints must include the optimizer state and random number generator states, and they must be frequent enough that rewinding does not waste much compute. LLaMA 3's 405B run saw 466 job interruptions in a 54-day period, 419 of them unexpected and most caused by hardware, so frequent, fast checkpoints are needed for reasons beyond loss spikes (Dubey et al. 2024, and §10.7).

Core

A gradient-norm spike detector

OLMo 2 tracks a spike score, the percentage of steps whose value is at least 7 standard deviations away from the rolling mean of the previous 1,000 values. Implement spike_steps(x, window=1000, k=7.0) returning the sorted list of indices t (with t >= window) for which abs(x[t] - mean) >= k * std, where mean and std (population standard deviation) are computed over x[t - window:t], the previous window values only. Also implement spike_score(x, window=1000, k=7.0) returning 100 * len(spike_steps(...)) / (len(x) - window). It must run in well under a second for 20,000 values.

Hidden tests, hints, and AI help, from $1.99 a month.
Warm-up

Plan a rewind

Write rewind_plan(spike_step, checkpoints, back=100, skip=300) returning (restart, skip_from, skip_to). restart is the latest checkpoint step that is at most spike_step - back. Training resumes from that checkpoint but skips the batches in the half-open range from skip_from = restart to skip_to = max(spike_step, restart) + skip, so the data that led into the spike, and a margin after it, is never replayed. Raise ValueError if no checkpoint is early enough.

Hidden tests, hints, and AI help, from $1.99 a month.

What to monitor

Most instabilities announce themselves before the loss moves, if you are watching the right numbers. A good dashboard for a pretraining run includes these, logged at least every few steps.

signalwhywarning sign
training loss, and loss on held-out sets per domainthe objective itself, and whether some domain is regressinga jump, or one domain rising while others fall
global gradient norm, before clippingthe earliest sign of troublesteady growth over thousands of steps, sudden jumps, a spike score above zero
fraction of steps clippedwhether clipping has become a hidden learning-rate changehigh outside warmup
update RMS divided by parameter RMS, per layerhow fast each layer is changingone layer far above the others, or near zero (a dead layer)
max attention logit and attention entropy, per layerlogit growth and entropy collapsemax logits rising steadily, entropy of a head falling toward 0
output log⁡Z\log Z statisticsoutput-logit driftmean far from 0 and moving
activation RMS per layerblow-ups in the residual streamexponential growth with depth or time
Adam statisticsstale or tiny second momentsmany coordinates with v^≲ϵ\sqrt{\hat v} \lesssim \epsilon
expert load in MoE modelsrouter collapse (§13.3)a few experts taking most tokens
throughput and model FLOPs utilizationstragglers, failing hardwarea sudden drop

In PyTorch

Here are z-loss and QK-norm as they appear in a real model, an attention module with RMS-normalized queries and keys and a language-model loss with a z-loss term, checked against our NumPy functions.

🔥 In PyTorchfor a machine with PyTorch

Read more

Watch next

🎬 OLMo leads on the secrets of training language models (w Dirk Groeneveld, Kyle Lo, & Luca Soldaini) · Interconnects AI · starts at 15:27The OLMo leads describe the loss spikes of a failed run and the fixes that made OLMo 2 stable.
🎬 This Simple Optimizer Is Revolutionizing How We Train AI | Muon · Jia-Bin Huang · starts at 11:49A clear visual account of exploding attention logits and how clipping the query and key weights contains them.