Training Objectives and Architectural Details
You will understand why every frontier model is a decoder-only causal language model, and you will be able to read a modern config file (RMSNorm, SwiGLU, RoPE, GQA, 128k vocabulary) and explain what problem each line solves, with the parameter arithmetic to back it up.
Open the GPT-2 you built in the from-scratch chapter next to the config for Llama 3 8B. They are both "transformers". Yet almost every line differs: a different normalization, a different activation, a different way to encode position, a different number of key heads than query heads, no bias terms anywhere, a vocabulary four times larger. Why? Each change was made because something broke, or something was wasteful, at scale.
This chapter has two parts. Part A asks the bigger question first: what should the model be trained to do? There were several serious candidates, and it is worth understanding why one of them won. Part B walks through the modern decoder block one component at a time, each with the problem it solves, the formula, a tiny worked example, and a picture.
Part A: What objective do we train on?
The transformer architecture does not come with a training objective. You choose one. Between 2018 and 2021 there were four serious contenders, and they produced very different models. The choice you make determines what every token in your corpus teaches the model, so it is worth being precise.
Causal language modeling (GPT)
The problem: we want a model that can generate text. The simplest objective that produces a generator is to predict each token from the ones before it. The model reads left to right and at every position outputs a distribution over the next token. The loss is the negative log-probability of the true next token, averaged over all positions.
$$\mathcal{L}_{\text{CLM}} = -\sum_{t=1}^{T} \log p_\theta(x_t \mid x_1, \dots, x_{t-1})$$What just happened: every one of the $T$ positions in the sequence contributes a loss term. A 4,096-token document gives 4,096 training signals from one forward pass. The causal mask in the attention layers is what makes this legal: position $t$ cannot see positions after it, so it cannot cheat.
Masked language modeling (BERT)
The problem BERT was solving was different: understanding, not generation. Devlin et al. (2018) reasoned that a left-to-right model sees only half the context for each prediction, and that for tasks like classification you want each token's representation to depend on both sides. So BERT hides 15% of the tokens and asks the model to fill them in, using bidirectional attention.
$$\mathcal{L}_{\text{MLM}} = -\sum_{t \in M} \log p_\theta(x_t \mid x_{\setminus M})$$Here $M$ is the set of masked positions and $x_{\setminus M}$ means the sequence with those positions replaced by a special [MASK] token. Only masked positions contribute to the loss. That is the catch: from a 512-token sequence you get about 77 training signals, not 512. And the model never learns to generate; it only learns to fill holes.
Prefix LM and seq2seq (T5)
Two hybrids tried to get the best of both. A prefix LM attends bidirectionally over a prefix (the "input") and causally over the rest (the "output"), training loss only on the output part. A seq2seq model like T5 (Raffel et al., 2020) has a separate encoder that reads the input bidirectionally and a decoder that generates the output causally with cross-attention into the encoder. T5's actual pre-training objective was "span corruption": drop out spans of the input and generate them in order.
Why decoder-only won for generation
By 2022 the question was settled empirically. Wang et al. (2022) trained all the variants at matched compute and found that causal decoder-only models pre-trained on plain next-token prediction gave the best zero-shot generalization after adaptation. The reasons are worth internalizing because they explain why nobody revisits the decision.
- Every token is a training signal. Per FLOP, the causal LM sees roughly six times as many supervised predictions as MLM with 15% masking. When compute is the binding constraint, this is decisive.
- It is simple. One stack, one mask, one loss. No encoder, no cross-attention, no span-corruption sampling scheme, no train-test mismatch from
[MASK]tokens that never appear at inference. - It scales cleanly. The KV cache, tensor parallelism, and every inference optimization in this course assume a single causal stack.
- Generation is the product. If what you sell is text coming out of the model, train the model to produce text. Understanding tasks can be phrased as generation ("The sentiment is: positive").
"Bidirectional is strictly more information, so BERT should be better." Per prediction, yes. Per unit of compute, no: BERT throws away 85% of the positions. And the causal model is not blind to the right context; it sees it at the next position. Over a whole document, the causal LM ends up modeling the same joint distribution, just factorized left to right.
Symbols
$x_t$ = token at position $t$$T$ = sequence length
$M$ = masked positions
$p_\theta$ = model's distribution
$\mathcal{L}$ = loss (lower is better)
Embed and mask
Look up token and position embeddings; build the causal mask so position $t$ sees only $1 \dots t$.Stack
Run $L$ identical decoder blocks: pre-norm, attention with residual, pre-norm, gated MLP with residual.Predict
Final norm, then the output projection to vocabulary logits at every position at once.Loss
Cross-entropy at every position against the shifted-by-one target; average; backpropagate.Part B: The modern decoder block
Now the block itself. Here is the same picture drawn twice: the 2019 block (GPT-2) and the 2024 block (Llama 3). Toggle between them and read the table of differences underneath. Then we will justify each row.
Same skeleton, different parts. Rows in the table that change are marked.
RMSNorm: normalization without the mean
The problem LayerNorm solves: activations in a deep residual stack drift in scale, and the next layer's matrix multiplication then sees inputs of wildly different magnitudes from one token to the next. LayerNorm (Ba et al., 2016) fixes this by standardizing each token's vector: subtract the mean, divide by the standard deviation, then apply a learned scale $\gamma$ and shift $\beta$.
$$\text{LayerNorm}(x) = \gamma \odot \frac{x - \mu}{\sqrt{\sigma^2 + \epsilon}} + \beta, \qquad \mu = \tfrac{1}{d}\textstyle\sum_i x_i,\quad \sigma^2 = \tfrac{1}{d}\sum_i (x_i - \mu)^2$$Zhang and Sennrich (2019) asked which part of that actually matters. Their answer: the re-scaling. The mean-centering contributes little. So RMSNorm drops the mean and the shift, and divides by the root-mean-square instead.
$$\text{RMSNorm}(x) = \gamma \odot \frac{x}{\sqrt{\tfrac{1}{d}\sum_i x_i^2 + \epsilon}}$$What just happened: we removed one reduction (the mean), one subtraction, and one learned vector ($\beta$). That is 10 to 15 percent less time in the normalization kernel, which matters because norms are memory-bound and run twice per layer. Quality, measured on the models that have tried both, is the same. Every major model since Llama 1 uses RMSNorm.
Take $x = [2, 4, 4, 6]$ with $\gamma = 1$, $\beta = 0$, $\epsilon = 0$.
LayerNorm. Mean $\mu = 4$. Deviations $[-2, 0, 0, 2]$. Variance $= (4 + 0 + 0 + 4)/4 = 2$, std $= 1.414$. Output: $[-1.41, 0, 0, 1.41]$.
RMSNorm. Mean of squares $= (4 + 16 + 16 + 36)/4 = 18$, RMS $= 4.243$. Output: $[0.47, 0.94, 0.94, 1.41]$.
Notice that RMSNorm preserved the fact that all entries were positive; LayerNorm centered them around zero. RMSNorm's output has unit RMS; LayerNorm's has unit variance. Now try both on $x + 100$ in the playground: LayerNorm does not care, RMSNorm collapses everything toward $[1,1,1,1]$.
Edit the six components, or shift all of them at once. Which normalization is invariant to the shift?
Pre-norm: where the normalization goes
The original transformer (Vaswani et al., 2017) put the norm after each residual addition: $x \leftarrow \text{Norm}(x + \text{Sublayer}(x))$. The problem: with post-norm, gradients at initialization are large in the top layers and tiny in the bottom, so training needs a careful warmup and is fragile in deep stacks (Xiong et al., 2020).
Pre-norm moves the norm inside the residual branch: $x \leftarrow x + \text{Sublayer}(\text{Norm}(x))$. Now the residual stream is a clean highway from input to output; every block only adds to it. GPT-2 already used pre-norm, and so does every model since. (A few recent models add a second norm on the branch output, "sandwich" or "peri" norm, for extra stability; Gemma 2 does this.)
SwiGLU: the gated MLP
The problem with the classic MLP: it is a fixed nonlinearity applied to a projection, $\text{GELU}(xW_1)W_2$. Every hidden unit fires based on one linear view of the input. Shazeer (2020) tried a small change borrowed from LSTMs: compute two projections, and let one of them gate the other by elementwise multiplication.
$$\text{SwiGLU}(x) = \big(\text{Swish}(xW) \odot xV\big)\, W_2, \qquad \text{Swish}(z) = z\,\sigma(z)$$What just happened: $xW$ passes through Swish (also called SiLU) and becomes a soft gate; $xV$ is the "content"; their product is the hidden activation, which $W_2$ projects back down. GeGLU is the same with GELU as the gate. The intuition for why it helps: a multiplicative interaction lets the MLP compute things like "feature A and feature B" in one layer, which a single nonlinearity cannot. Shazeer's paper offers no theory, only the honest line that "we offer no explanation... and attribute their success, as all else, to divine benevolence", but the perplexity improvements have held up at every scale since, and PaLM, Llama, Mistral and Gemma all use a gated MLP.
Let $x = [1, 2]$, $W = \begin{bmatrix}1 & 0\\ 0 & -1\end{bmatrix}$, $V = \begin{bmatrix}1 & 1\\ 1 & 0\end{bmatrix}$ (hidden width 2).
Gate input $xW = [1, -2]$. Swish: $1\cdot\sigma(1) = 0.731$ and $-2\cdot\sigma(-2) = -0.238$. So the gate is $[0.731, -0.238]$.
Content $xV = [3, 1]$. Product: $[2.19, -0.24]$. Then $W_2$ would project this back to 2 dimensions.
The first hidden unit is "on" (positive gate) and passes most of its content; the second is nearly "off" and even slightly negative. Swish is not a hard gate: it leaks a little for negative inputs, which keeps gradients alive.
Gated linear units go back to Dauphin et al. (2017), who used them in convolutional language models. Shazeer (2020) tried the GLU family inside the T5 transformer MLP and found the Swish- and GELU-gated variants gave the best perplexity; PaLM (2022) and Llama (2023) made SwiGLU the default.
The 8/3 hidden multiplier
The gated MLP has three matrices instead of two. If you kept the hidden width at $4d$ the MLP would cost 50% more parameters. To keep the parameter count matched, papers shrink the hidden width. Standard MLP: $W_1$ is $d \times 4d$ and $W_2$ is $4d \times d$, total $8d^2$. Gated MLP with hidden width $h$: $W$, $V$ are $d \times h$ and $W_2$ is $h \times d$, total $3dh$. Setting $3dh = 8d^2$ gives:
$$h = \tfrac{8}{3}\, d \approx 2.67\, d$$Llama 1 and 2 use exactly this, rounded up to a multiple of 256 (for $d = 4096$: $10{,}923 \to 11{,}008$). Llama 3 8B multiplies by a further 1.3 and rounds to a multiple of 1024, giving $14{,}336 = 3.5d$; the extra width is spent on purpose because the MLP is where knowledge lives and the 128k vocabulary freed up budget elsewhere.
Left: the gate functions. Right: how wide the hidden layer can be for the same parameter budget.
RoPE: a recap and a pointer
The problem with GPT-2's learned absolute position embeddings: they are a lookup table of 1,024 vectors. Position 1,025 does not exist. And "how far apart are these two tokens" has to be inferred from two absolute vectors, which is a clumsy way to encode the thing attention actually cares about.
Rotary position embedding (Su et al., 2021) instead rotates each query and key vector by an angle proportional to its position, in a set of 2-d planes with different frequencies. Because a dot product between two rotated vectors depends only on the difference of their angles, the attention score depends only on relative position. It is applied inside every attention layer, not once at the input, and it adds no parameters. You built it in the positional encoding chapter; here the only new fact is the base frequency: Llama 3 raised $\theta$ from 10,000 to 500,000 so that the lowest-frequency planes rotate slowly enough to distinguish positions up to 128k apart.
Grouped-query attention: shrinking the KV cache
The problem does not show up in training at all. It shows up at inference. To generate token $t+1$ the model needs the keys and values of all previous tokens in every layer, and recomputing them every step would be absurd, so they are cached. The KV cache per sequence is:
$$\text{bytes} = 2 \times L_{\text{layers}} \times n_{kv} \times d_{\text{head}} \times T \times \text{bytes per value}$$The leading 2 is for K and V. In standard multi-head attention (MHA) $n_{kv}$ equals the number of query heads, and the cache is enormous. Multi-query attention (MQA; Shazeer, 2019) shares one K and one V head across all query heads, dividing the cache by $n_{\text{heads}}$, but costs some quality. Grouped-query attention (GQA; Ainslie et al., 2023) is the compromise: put query heads into $g$ groups and give each group its own K/V head.
80 layers, 64 query heads, $d_{\text{head}} = 128$, context 4,096, fp16 (2 bytes).
MHA ($n_{kv} = 64$): $2 \times 80 \times 64 \times 128 \times 4096 \times 2 = 10.7$ GB per sequence. An 80 GB GPU that already holds 140 GB of weights (it cannot; you need two) has room for almost no concurrent requests.
GQA ($n_{kv} = 8$): $2 \times 80 \times 8 \times 128 \times 4096 \times 2 = 1.34$ GB per sequence. Eight times smaller. That is why the 70B got GQA in Llama 2 and every size got it in Llama 3.
MQA ($n_{kv} = 1$): 168 MB. Even smaller, but the papers report a measurable quality loss; 8 KV heads is the sweet spot most models settled on.
KV cache size in fp16 for one model configuration under MHA, GQA and MQA. Start with Llama 2 70B and drag the context length up.
No bias terms
GPT-2 has a bias vector on every linear layer and every LayerNorm. Llama has none. The problem they solved by removing them is subtle: PaLM (Chowdhery et al., 2022) reported that dropping biases improved training stability for large models, and nobody has found a quality cost. Biases are a negligible fraction of parameters, so the saving is not about size; it is one fewer thing that can drift. The RMSNorm scale $\gamma$ stays.
Untied embeddings
GPT-2 uses the same matrix to embed input tokens and to produce output logits ("weight tying", Press and Wolf, 2017). For a small model this saves a large fraction of parameters and acts as a regularizer. The problem at scale: the two jobs are different. The input embedding wants to represent "what this token means"; the output projection wants to represent "what predicts this token next". Llama 3 8B unties them, spending an extra $128{,}256 \times 4{,}096 \approx 525$M parameters, about 6.5% of the model, on a separate output head. Whether this is worth it depends on the model: Gemma keeps tying because its huge 256k vocabulary would otherwise dominate the parameter count at small sizes.
QK-norm
The problem: attention logits are $q \cdot k / \sqrt{d}$, and if the norms of $q$ and $k$ grow during training, the logits grow, the softmax saturates, and gradients vanish or explode. This is a leading cause of the loss spikes discussed in the next chapter. QK-norm (Henry et al., 2020; used at scale by Dehghani et al., 2023 in ViT-22B) applies a normalization to $q$ and $k$ separately before the dot product, so the logit magnitude is bounded by the learned scale rather than by whatever the projections drift to. OLMo 2 and Gemma 3 adopt it. The cost is two extra small norms per layer.
Attention logit soft-capping
A blunter tool for the same problem: pass each logit through a scaled $\tanh$ so it can never exceed a cap.
$$\text{softcap}(z) = c \cdot \tanh(z / c)$$For $|z| \ll c$ the function is nearly the identity; for large $|z|$ it saturates at $\pm c$. Gemma 2 (Gemma Team, 2024) uses $c = 50$ on attention logits and $c = 30$ on the final output logits. With $c = 50$, a logit of 10 becomes $50\tanh(0.2) = 9.87$ (almost unchanged) and a logit of 200 becomes $50\tanh(4) = 49.97$ (clamped). The downside: fused attention kernels like FlashAttention need explicit support for the extra nonlinearity, which delayed adoption.
Sliding-window attention
The problem: full attention over a 128k context costs $O(T^2)$ per layer and a KV cache of 128k entries per layer. Sliding-window attention (Beltagy et al., 2020) restricts each token to attend to only the previous $w$ tokens. Information from further back still arrives, but indirectly: after $\ell$ layers the receptive field is $\ell \cdot w$. Mistral 7B (Jiang et al., 2023) used $w = 4096$ in every layer. Gemma 2 alternates local (window 4096) and global layers so that some layers still see everything. This caps the KV cache of the local layers at $w$ entries regardless of context length.
Larger vocabularies
GPT-2 had 50,257 tokens; Llama 1 and 2 had 32,000; Llama 3 jumped to 128,256; Gemma uses 256,000. The problem: with a small vocabulary, non-English text and code fragment into many tokens. Llama 3 reports that its tokenizer needs about 15% fewer tokens than Llama 2's for the same English text, and much fewer for other languages. Fewer tokens per document means each training token carries more information and each generated token gets you further, so at fixed compute the model effectively sees more text. Tao et al. (2024) fit scaling laws for vocabulary size and find the optimal vocabulary grows with model size, which argues that older models were too small in this dimension. The costs are a bigger embedding table, a bigger output softmax, and rarer tokens that each get fewer training examples.
Context length and how it is grown
Why not train at 128k context from the start? Because attention cost grows with the square of the sequence length within a batch, and because most training documents are short; padding or packing them into 128k windows would waste compute on cross-document attention. So the standard recipe (Llama 3, and most others) trains at a modest length (8,192 tokens for Llama 3) for almost all of the tokens, then runs a long-context stage at the end.
Llama 3 grew context in six stages from 8k to 128k, on about 800B tokens, at each stage waiting until short-context evaluations recovered and needle-in-a-haystack retrieval worked at the new length. RoPE's base frequency is raised to match (500,000 for Llama 3). This is cheap relative to the main run and gives you most of the long-context capability. The advanced objectives chapter covers the mechanics.
The config sheet: Llama 3 8B, with the arithmetic
Here is the actual configuration. Then we count every parameter by hand, because being able to do this is the difference between reading a config file and understanding it.
| Field | Value | Meaning |
|---|---|---|
dim | 4096 | $d_{\text{model}}$, width of the residual stream |
n_layers | 32 | decoder blocks |
n_heads | 32 | query heads; $d_{\text{head}} = 4096/32 = 128$ |
n_kv_heads | 8 | key/value heads; 4 query heads per group |
ffn hidden | 14336 | SwiGLU hidden width, $= 3.5d$ |
vocab_size | 128256 | tokens |
rope_theta | 500000 | RoPE base frequency |
norm_eps | 1e-5 | RMSNorm $\epsilon$ |
| context | 8192 | pre-training sequence length (128k after long-context stage) |
Counting the parameters
Per layer, attention has four matrices. $W_Q$ and $W_O$ are full $d \times d$; $W_K$ and $W_V$ are $d \times (n_{kv} \cdot d_{\text{head}}) = 4096 \times 1024$.
$$W_Q: 4096 \times 4096 = 16{,}777{,}216 \qquad W_O: 16{,}777{,}216 \qquad W_K, W_V: 4096 \times 1024 = 4{,}194{,}304 \text{ each}$$Attention per layer: $16.78\text{M} \times 2 + 4.19\text{M} \times 2 = 41{,}943{,}040$. The gated MLP has three matrices of $4096 \times 14336$:
$$3 \times 4096 \times 14336 = 176{,}160{,}768$$Two RMSNorms add $2 \times 4096 = 8{,}192$. Per layer total: $41{,}943{,}040 + 176{,}160{,}768 + 8{,}192 = 218{,}112{,}000$. Times 32 layers: $6{,}979{,}584{,}000$.
Outside the layers: the input embedding $128{,}256 \times 4096 = 525{,}336{,}576$, the untied output head of the same size, and a final RMSNorm of 4,096.
$$N = 6{,}979{,}584{,}000 + 2 \times 525{,}336{,}576 + 4{,}096 = 8{,}030{,}261{,}248$$That is 8.03B, matching the reported size. Two observations fall out. The MLP is 81% of each layer; that is where the knowledge lives. And the two embedding matrices are 13% of the whole model, which is why the vocabulary size decision is not free.
With 32 KV heads instead of 8, $W_K$ and $W_V$ would each be $16.78$M, adding $25$M per layer and $805$M total. GQA is usually sold as an inference optimization, but it also trims about 10% of the attention parameters, which the config spends on the wider MLP.
Companion code
Everything above is implemented in code/lumen/block.py: RMSNorm, SwiGLU, and a TransformerBlock that can be configured as GPT-2-style or Llama-style. The attention module in code/lumen/attention.py takes n_kv_heads and repeats K and V across groups. The heart of it is short enough to show here.
import torch, torch.nn as nn, torch.nn.functional as F
class RMSNorm(nn.Module):
def __init__(self, d, eps=1e-5):
super().__init__()
self.eps = eps
self.weight = nn.Parameter(torch.ones(d)) # gamma only, no beta
def forward(self, x):
rms = x.pow(2).mean(-1, keepdim=True).add(self.eps).rsqrt()
return x * rms * self.weight
class SwiGLU(nn.Module):
def __init__(self, d, hidden):
super().__init__()
self.w_gate = nn.Linear(d, hidden, bias=False)
self.w_up = nn.Linear(d, hidden, bias=False)
self.w_down = nn.Linear(hidden, d, bias=False)
def forward(self, x):
return self.w_down(F.silu(self.w_gate(x)) * self.w_up(x))
def swiglu_hidden(d, multiplier=1.0, multiple_of=256):
h = int(2 * (4 * d) / 3 * multiplier) # 8/3 * d, times an optional factor
return multiple_of * ((h + multiple_of - 1) // multiple_of)
print(swiglu_hidden(4096), swiglu_hidden(4096, 1.3, 1024))
The first number is Llama 2 7B's hidden size; the second is Llama 3 8B's. The helper reproduces both from the rule.
Practice
Llama 3 70B has $d = 8192$, 80 layers, 64 heads, 8 KV heads, hidden 28,672, vocab 128,256, untied embeddings. Count its parameters by hand as we did for 8B and compare with the reported 70.6B.
Solution sketch
$d_{\text{head}} = 128$. Attention: $W_Q, W_O = 8192^2 = 67.1$M each; $W_K, W_V = 8192 \times 1024 = 8.39$M each; total $151$M. MLP: $3 \times 8192 \times 28672 = 704.6$M. Norms: 16k. Per layer $\approx 855.6$M; times 80 $= 68.45$B. Embeddings: $2 \times 128256 \times 8192 = 2.10$B. Total $\approx 70.55$B. Matches.
Using code/lumen/attention.py and code/lumen/block.py, construct a block with 8 query heads and 2 KV heads on $d = 256$. Verify that (a) the output shape matches the input, (b) the parameter count of the attention module equals $d^2 \cdot (2 + 2 \cdot n_{kv}/n_{\text{heads}})$, and (c) with n_kv_heads = n_heads you recover standard MHA exactly, by comparing outputs against your MHA from the attention chapter with the same weights.
Solution sketch
For (b): $W_Q$ and $W_O$ are $d^2$ each; $W_K$ and $W_V$ are $d \times (n_{kv} \cdot d/n_{\text{heads}})$ each. With $n_{kv}/n_{\text{heads}} = 1/4$: $d^2(2 + 0.5) = 2.5 d^2 = 163{,}840$. For (c), the GQA implementation repeats each KV head $n_{\text{heads}}/n_{kv}$ times with repeat_interleave; when that ratio is 1 nothing is repeated and the computation is identical.
Train two tiny models (4 layers, $d = 128$) on the corpus in code/lumen/data.py for 500 steps with code/lumen/train.py: one with LayerNorm, one with RMSNorm. Compare final loss and time per step. Then repeat with a GELU MLP (hidden $4d$) versus SwiGLU (hidden $8d/3$, rounded to a multiple of 8) at matched parameter count.
Solution sketch
At this scale the losses will be within noise of each other; the point is to confirm that RMSNorm is a drop-in replacement and that the gated MLP at $8d/3$ has the same parameter count (check with a sum over numel()). The speed difference will be invisible on CPU because the matmuls dominate; on a GPU with a profiler you can see the norm kernel time drop.
Key takeaways
- Causal next-token prediction won because it turns every token into a training signal, is simple, and is what generation needs.
- RMSNorm drops the mean and the shift from LayerNorm; pre-norm keeps the residual stream as a clean highway.
- SwiGLU gates the MLP with a Swish-activated second projection; hidden width 8d/3 keeps parameters matched to a 4d MLP.
- RoPE encodes relative position inside attention; GQA shares KV heads across query groups and shrinks the KV cache by n_heads/n_kv.
- No biases, untied embeddings, QK-norm and soft-capping are stability and capacity choices that only matter at scale.
- You can count a model's parameters from its config: for Llama 3 8B, 32 × 218.1M + 2 × 525.3M ≈ 8.03B.
Further reading
- Wang et al. (2022). What Language Model Architecture and Pretraining Objective Work Best for Zero-Shot Generalization? The controlled comparison of objectives.
- Zhang and Sennrich (2019). Root Mean Square Layer Normalization. RMSNorm.
- Xiong et al. (2020). On Layer Normalization in the Transformer Architecture. Why pre-norm trains more easily.
- Shazeer (2020). GLU Variants Improve Transformer. SwiGLU and GeGLU; short and worth reading in full.
- Su et al. (2021). RoFormer: Enhanced Transformer with Rotary Position Embedding. RoPE.
- Ainslie et al. (2023). GQA: Training Generalized Multi-Query Transformer Models from Multi-Head Checkpoints. Grouped-query attention.
- Shazeer (2019). Fast Transformer Decoding: One Write-Head is All You Need. Multi-query attention and the KV-cache argument.
- Henry et al. (2020). Query-Key Normalization for Transformers. QK-norm.
- Gemma Team (2024). Gemma 2: Improving Open Language Models at a Practical Size. Logit soft-capping and alternating local/global attention.
- Jiang et al. (2023). Mistral 7B. Sliding-window attention in a production model.
- Tao et al. (2024). Scaling Laws with Vocabulary. Larger models want larger vocabularies.
- Grattafiori et al. (2024). The Llama 3 Herd of Models. The config sheet's source.