SK (online)

ENGINEERING BLOG / CHAPTER 03 OF 10

Inside Modern Attention: Positions, Normalization and Efficiency

Saravan Kumar M KUpdated 2026-10-26~39 min read10 sections

3.1 — The Attention Mechanism

Why Self-Attention at All

Before transformers, language models used RNNs, which read a sentence one word at a time, left to right. If word 1 mattered for understanding word 100, that information had to survive a 99-step relay race through every word in between. Over long distances, it faded — this is the classic “long-range dependency” problem.

Main idea: Self-attention throws out the relay race. Every token looks directly at every other token, all at once, in a single step. No middlemen, no fading signal.

Self-Attention: The Core Idea

Take a sentence of tokens. Each token starts life as an embedding vector — just a list of numbers representing that word’s meaning, with no notion of position yet.

We learn three weight matrices that transform each embedding into three different-purpose vectors:

where:

  • — the Query projection matrix. Learned during training.
  • — the Key projection matrix. Learned during training.
  • — the Value projection matrix. Learned during training.
  • — the size of the input embedding for each token.
  • — the size of the Query and Key vectors (they must match, since we’ll take their dot product).
  • — the size of the Value vectors (can differ from ).

For every token, we multiply its embedding by each matrix to get three vectors:

where: is token ’s embedding; are the Query, Key, and Value vectors produced for token .

A useful analogy: imagine a library. Every book (token) has a Key — a short label describing what it’s about. Every reader (also a token, since every token both asks and answers) has a Query — what they’re currently searching for. When a Query matches a Key well, that book’s Value — its actual content — gets pulled in and read.

In matrix form, stack every token’s embedding into one big matrix (one row per token) and do all the projections at once:

where: , , — each row corresponds to one token’s Query, Key, or Value vector.

The full attention computation is:

where:

  • — every Query dotted with every Key, producing a raw “relevance score” for every pair of tokens.
  • — a scaling factor explained in the next section.
  • — turns each row of scores into a probability distribution (values between 0 and 1, summing to 1 per row).
  • The final multiplication by — blends the Value vectors according to those probabilities.

Main idea: Attention is a soft, learned lookup: for each token, compute how well its Query matches every other token’s Key, turn those match-scores into weights, and use the weights to build a blended mixture of everyone’s Value vectors.

Why Divide by the Square Root of d_k

The dot product is a sum of individual multiplications. As grows, this sum tends to grow larger in magnitude too (more terms being added up). Very large scores push softmax into a “saturated” regime — one score dominates completely, the rest collapse toward zero, and the gradients used for learning become vanishingly small everywhere.

Dividing by rescales the scores so their variance stays close to 1 regardless of how large is. It’s purely a numerical-stability fix — it keeps softmax’s inputs in a healthy range so training gradients keep flowing.

where: is the dimensionality of the Query/Key vectors (defined in 1.2).

What the QK Transpose Matrix Looks Like

where: is the number of tokens in the sequence. The result is a square matrix — one row and one column per token.

Entry of this matrix is : how strongly token ’s Query matches token ’s Key — in other words, how much token should attend to token . After the softmax, every row sums to exactly 1, so row becomes a clean probability distribution describing “how token splits its attention across the whole sequence.”

Multiplying this weight matrix by then gives each token a new representation: a weighted average of every token’s Value vector, weighted exactly by that attention distribution. This new representation is what carries contextual information forward into the rest of the network.

The Permutation Invariance Problem

Here’s the catch. Everything in “Self-Attention: The Core Idea” (Section 3.1) — , softmax, the multiplication by — is built entirely out of dot products between vectors. Nowhere does the actual order of tokens enter the computation.

Self-attention treats its input as a set: reordering the tokens only reorders the outputs.

If you shuffle the input tokens:

self-attention produces the exact same pairwise relevance scores, just relabeled. It has no way to know that originally came first.

This property is called permutation invariance — the function’s output doesn’t change based on token order, only on which tokens are present.

“Dog bites man” and “Man bites dog” contain the same three word vectors. Without positional information, a transformer literally cannot tell them apart.

Main idea: Self-attention is order-blind by design. Positional encoding isn’t a nice-to-have add-on — it’s a mandatory fix for a real gap in the architecture, and it’s the whole subject of Parts 2–6.

Multi-Head Attention (MHA)

A single attention computation learns one type of relationship between tokens — say, subject-verb agreement. But language has many simultaneous relationship types: syntax, coreference (“it” refers to what?), semantic similarity, and more. Multi-Head Attention runs independent attention computations (“heads”) in parallel, each with its own learned projections, so each head can specialize in a different kind of relationship.

For head :

where: is the total number of heads; are head ’s own private projection matrices, distinct from every other head’s.

Every head’s output gets glued together side-by-side (concatenated) and passed through one more learned matrix to mix the heads back into a single representation:

where: is the output projection matrix, which combines all heads’ outputs into one vector of the original model dimension .

Typical setup: with heads gives per head — the total parameter count is kept similar to a single wide head, but the model gets independent “perspectives” instead of .

Main idea: More heads = more simultaneous relationship types the model can track, at roughly the same total compute cost as one big head.

The KV Cache Problem

During inference — generating text one token at a time — producing the next token requires attending to every previous token’s Key and Value vectors. Recomputing all of them from scratch at every single step, for every new token, would be enormously wasteful, since past tokens’ Keys and Values never change once computed.

Multi-head, grouped-query and multi-query attention differ only in how many key/value sets the query heads share.

The fix: compute each token’s and once, and store them in memory for reuse at every future step. This stored memory is the KV Cache.

The problem is size. The cache must hold Key and Value vectors for every past token, across every head, across every layer:

where:

  • — because we store both and .
  • — number of tokens processed so far (grows as generation continues).
  • — number of attention heads.
  • — size of each head’s Value vector.
  • bytes per element — how many bytes each number takes (e.g., 2 bytes for FP16).

For a 1-million-token context with 128 heads, this reaches hundreds of gigabytes. This cache — not raw compute — is the main bottleneck for serving long-context language models efficiently.

Main idea: The KV cache trades memory for speed. As context length grows, that memory bill becomes the real constraint — which is exactly the problem MQA, GQA, and MLA (next three sections) are all designed to solve.

Multi-Query Attention (MQA)

Idea: Keep every head’s own Query, but force all heads to share one single Key and one single Value.

where: is the number of distinct Key/Value groups. Setting means there’s only one shared group for all heads.

where: is head ’s own private Query, but and are the same shared vectors used by every head.

KV cache reduction: Instead of storing separate Key vectors and separate Value vectors, you store just of each — an reduction in cache size.

Tradeoff: Quality dips slightly, because every head is now forced to see the same Key/Value “view” of each token — the diversity that made multiple heads useful in the first place is partly lost. The memory savings, though, are large.

Grouped Query Attention (GQA)

Idea: A middle ground between full MHA (every head has its own K/V) and MQA (all heads share one K/V). Split the query heads into groups; heads inside the same group share one Key and Value.

For group , containing query heads :

where: are the single shared Key and Value vectors for every head inside group ; is the number of query heads per group.

KV cache size ends up smaller than full MHA, and larger than MQA — a tunable sweet spot. GQA is used in LLaMA 2, Mistral, and most modern open models, because it recovers almost all of MHA’s quality while cutting cache size substantially.

Multi-Head Latent Attention (MLA)

MQA and GQA save memory by making heads share Keys and Values. MLA (DeepSeek’s approach) takes a completely different route: it compresses the K/V information itself into a much smaller vector, before it’s ever split into heads.

MLA caches one small latent vector per token and rebuilds each head’s keys and values from it.

Main idea: Don’t share heads — shrink what you’re storing per token down to a tiny compressed code, and reconstruct the full-quality Keys and Values from that code only when needed.

The core compression trick

Instead of storing a full-size Key and Value for every head, MLA stores one small latent vector per token:

where:

  • — the token’s input embedding.
  • — the down-projection matrix (the marks “compressing down”).
  • — the compressed latent vector actually stored in the cache.
  • — the latent dimension, chosen to be much smaller than the total size of all heads’ K/V combined ().

When attention actually needs to run, each head reconstructs its own Key and Value by up-projecting the shared latent:

where: are head ’s private up-projection matrices (the marks “decompressing back up” to full size), applied on the fly rather than stored.

What actually sits in the cache: just , a vector of size — not separate Keys and separate Values.

If , this is a massive memory win — and unlike MQA/GQA, no head is forced to share its view; each head still gets a full, unique Key and Value reconstructed from the shared latent.

The matrix absorption trick (an inference speed-up)

At inference time, head ’s attention score involves:

where: and are the equivalent down/up-projection matrices on the Query side; is the current token’s embedding.

Because matrix multiplication is associative, and can be pre-multiplied together once, offline, into a single fixed matrix:

where: is this pre-merged matrix for head — computed once, ahead of time, and reused at every inference step.

The dot product then simplifies to:

The consequence: the model never has to explicitly reconstruct the full Key vector at inference time — it applies directly to the cached latent . The same trick merges the Value up-projection with the output matrix .

The payoff: MLA gets the memory footprint and inference speed roughly on par with MQA, but the attention quality of full multi-head attention — because it never actually threw away per-head information, it just compressed and later reconstructed it.

3.2 — Why We Need Positional Encoding

The Properties We Need

Since self-attention is order-blind (“The Permutation Invariance Problem” (Section 3.1)), we need to explicitly inject position information via a positional encoding vector for each position . A good one should satisfy:

  1. Uniqueness: whenever — every position gets a distinct signature.
  2. Smoothness: nearby positions get similar-looking encodings (position 5 should resemble position 6 more than it resembles position 5000).
  3. Relative recoverability: from and alone, the model should be able to work out the distance .
  4. Extrapolation: it should keep working sensibly on sequences longer than any seen during training.

The standard way to inject it is simple addition to the word embedding before anything else happens:

where: is token ’s word embedding (pure meaning, no position); is its positional encoding; is the combined vector that actually enters the attention and feed-forward layers.

Two Families of Positional Encoding

Learned (absolute): a trainable lookup table , where position simply gets whatever vector the model learned during training. where: is the maximum sequence length seen during training. Problem: since it’s just a lookup table, it has no idea what to output for positions beyond — it cannot extrapolate.

Rule-based (fixed): a mathematical formula, with no learned parameters, that can be evaluated at any position — including ones never seen in training. This is the family Parts 3–5 explore.

3.3 — Sinusoidal Positional Encoding

The Formula

The original “Attention Is All You Need” paper defines position ’s encoding using sine and cosine pairs across the embedding dimensions:

where:

  • — the token’s position (0, 1, 2, …).
  • — the total embedding dimension.
  • — a dimension-pair index, running from to ; each picks out one sin/cos pair of dimensions.

It’s cleaner to define a frequency per pair:

so that the formula becomes just:

The Intuition: Multiple Clocks

Different dimension pairs oscillate at different speeds:

Each pair of dimensions oscillates at its own frequency, so every position gets a unique fingerprint.
  • : — fast, changes noticeably at every single position.
  • : — slower.
  • : — extremely slow, barely moves across thousands of positions.

Main idea: Think of an analog clock. The second hand alone can’t tell you the hour; the hour hand alone can’t tell you the second. But together, seconds + minutes + hours uniquely pin down any moment in a 12-hour span. Sinusoidal PE does the same trick with many “hands” spinning at exponentially different speeds — together they uniquely fingerprint any position.

Numerical Walkthrough (d = 4)

With , there are only two frequency pairs: and .

For : , so and .

For : , so and .

Position Dim 0: Dim 1: Dim 2: Dim 3:
0 0 1 0 1
1 0.8415 0.5403 0.0100 0.9999
2 0.9093 −0.4161 0.0200 0.9998
3 0.1411 −0.9900 0.0300 0.9996

Dims 0–1 swing rapidly across just four positions. Dims 2–3 barely budge. Together, the four numbers form a unique fingerprint per position — exactly like the clock analogy above.

The Relative Position Property (Key Math)

This is the property that makes sinusoidal encoding genuinely elegant, not just clever bookkeeping.

Claim: for any fixed offset , there’s a rotation matrix — depending only on , never on — that maps position ’s encoding to position ’s encoding:

where: is the offset between two positions; is the frequency for pair (as in 3.1); is the starting position.

Proof sketch, via the standard angle-addition identities:

These two identities are literally the matrix equation above, written out. Crucially, ’s entries depend only on .

Why this matters in practice: the dot product between two positional encodings works out to a function of the distance between them, not their absolute positions:

This is a function of only. So even though the encoding is added in absolute form, the attention mechanism — which works via dot products — can implicitly extract relative position information from it.

Why Not Simpler Encodings

Raw position numbers (): the model would see huge numeric jumps as sequences get longer, with no periodic structure and no way to recover relative distance cleanly.

One-hot vectors (, ): positions 2 and 3 look exactly as “different” from each other as positions 2 and 5000 — there’s no notion of smoothness or nearness at all.

Sinusoidal: multi-scale (many frequencies), periodic, unique per position, smooth between neighbors, and relative-distance-recoverable — all with zero learned parameters, and it generalizes to any sequence length.

3.4 — From Absolute to Relative Positional Encoding

The Problem with Absolute Encoding

Standard transformers add straight into the token embedding — this is absolute positional encoding, since each token’s stamp depends only on its own index .

But look at what attention actually needs: when deciding how much token should attend to token , what matters is the gap between them, not their individual absolute positions. Two tokens 3 apart at the start of a document should relate the same way as two tokens 3 apart near the end.

Main idea: this observation motivates a shift — instead of stamping position onto the input embeddings, inject relative position directly into the attention score computation itself. Parts 4–5 are all instances of this shift.

T5 Relative Bias

Idea: add a learned scalar bias directly onto the raw attention logit:

where: is a learned bias term depending on the positions and .

T5 makes depend only on the distance , and buckets that distance — many different distances share the same learned value:

where: is a learned parameter, one per attention head, indexed by which bucket the distance falls into.

Why bucket? To generalize past training length. If training only ever saw distances up to 128, distances from 64–128 get grouped into one shared bucket; at inference, distances beyond training length still fall gracefully into that last bucket instead of hitting an undefined case.

Limitation: is a real learned parameter per head — it still has to be trained, and generalization to lengths far beyond training remains imperfect.

ALiBi: Attention with Linear Biases

Idea (Press et al., 2021): skip learning entirely — use a fixed, deterministic linear penalty based purely on distance:

ALiBi adds a linear penalty, growing with distance, directly to the attention scores.

where: is a fixed, head-specific slope, chosen ahead of time (not learned); since for a past token , the term is negative, so the bias is always negative — the farther back a token is, the harsher the penalty.

Each head is assigned a different slope (typically a geometric sequence like ) — some heads penalize distance sharply (stay very local), others gently (can still reach far).

Key properties:

  • Zero learned parameters for position.
  • Naturally biases attention toward nearby tokens by default.
  • Extrapolates cleanly to sequences longer than training — the linear penalty just keeps extending, with no undefined behavior.

Visually, the attention matrix ends up with a triangular pattern of steadily increasing penalty the further back you look.

3.5 — Rotary Positional Embedding (RoPE)

The Core Idea

RoPE (Su et al., 2021) takes yet another angle: instead of adding a position vector to the input, or adding a bias to the score, it rotates the Query and Key vectors themselves — by an angle proportional to their position — right inside the attention computation.

Main idea: if you rotate by an angle proportional to , and by an angle proportional to , then their dot product depends only on the difference — the absolute positions cancel out algebraically, automatically, with no learning required.

2D Rotation: The Building Block

In just 2 dimensions, rotating a vector by angle uses the standard rotation matrix:

RoPE rotates queries and keys by position-dependent angles; only the gap between positions matters.

Rotate the Query by angle and the Key by angle :

where: is a fixed base angle; are the two token positions; are the rotated Query and Key.

Now take their dot product:

This uses two rotation-matrix facts: (transposing a rotation reverses it), and (composing two rotations adds their angles).

The result depends only on — the individual values of and disappear entirely, leaving pure relative distance baked directly into the dot product.

Extension to Many Dimensions

Real Query/Key vectors have dimensions, not 2. RoPE handles this by splitting the vector into independent 2D pairs, each rotating at its own frequency:

where: indexes which pair of dimensions we’re looking at; is that pair’s rotation frequency — exactly the same multi-frequency idea as sinusoidal PE in Part 3.

The full rotation is block-diagonal — each pair rotates independently of every other pair:

The relative-distance property survives intact across all pairs:

where: are the raw token embeddings; are the Query/Key projection matrices; is the block-diagonal rotation for the relative distance . The final attention score is a function of relative distance only — nothing about absolute position leaks through.

Practical Implementation of RoPE

In real code, the block-diagonal matrix is never explicitly built (that would be wasteful). Instead, for a vector split into consecutive pairs , each pair is rotated with simple element-wise arithmetic:

where: are the original vector’s individual entries, grouped into consecutive pairs, each pair rotated by its own frequency from “Extension to Many Dimensions” (Section 3.5).

This is just multiplications and additions — no matrix construction needed — which is exactly the kind of operation GPUs handle extremely efficiently.

The Long-Term Decay Property

RoPE has a bonus emergent behavior: the maximum possible attention score between two tokens naturally shrinks as their distance grows.

Averaged over the frequency pairs, RoPE’s position-dependent term shrinks as the distance grows.

Why: each frequency pair contributes a term , and different pairs oscillate at different phases. For large distances, these many out-of-sync cosine terms partially cancel each other out (destructive interference), pulling the overall achievable score down.

Consequence: RoPE builds in a mild recency bias for free — nearby tokens tend to be easier to attend to strongly than very distant ones, which loosely matches how language actually works (nearby context is usually more relevant).

Why RoPE Is the Default Choice Today

Property Sinusoidal T5 Bias ALiBi RoPE
Learned parameters No Yes () No No
Relative encoding Approximate Exact Exact Exact
Long-range decay No No Yes (linear) Yes (natural)
Applied inside attention layer No Yes Yes Yes
Used in GPT-4 / LLaMA-class models No No No Yes

RoPE checks every box: no extra parameters to learn, exact relative-distance encoding, natural long-range decay, and a clean, GPU-friendly implementation. It’s the default in LLaMA 1/2/3, Mistral, DeepSeek, Qwen, and nearly every modern open LLM.

3.6 — DeepSeek’s Decoupled RoPE and Partial RoPE

The Conflict Between MLA and RoPE

Here’s a subtle engineering snag: MLA caches only the compressed latent (“Multi-Head Latent Attention (MLA)” (Section 3.1)) — it deliberately never materializes the full Key vectors. But standard RoPE needs to rotate the actual Key vector by an angle depending on its position, before the dot product happens:

where: is the cached latent for token ; is head ’s up-projection (from “Multi-Head Latent Attention (MLA)” (Section 3.1)); is RoPE’s position-dependent rotation for position .

The problem: depends on , but is cached without that rotation baked in — because rotation must be applied fresh depending on how far away the current query token is. This wrecks the matrix absorption trick from “Multi-Head Latent Attention (MLA)” (Section 3.1): you can no longer pre-merge and into one fixed matrix ahead of time, because a position-dependent rotation now sits in between them, and that rotation is different for every single cached token.

Main idea: MLA’s core efficiency trick and standard RoPE are architecturally at odds — you can’t cleanly have both at the same time.

Decoupled RoPE: DeepSeek’s Solution

The fix: split each token’s representation into two separate streams that serve two separate jobs.

  • Content stream: the compressed latent from MLA, used for content-based matching — RoPE is never applied here, so the matrix-absorption speed-up (“Multi-Head Latent Attention (MLA)” (Section 3.1)) stays fully intact.
  • Position stream: a small, separate, uncompressed pair of vectors — for Keys and for Queries — to which RoPE is applied.

where: are dedicated projection matrices just for this small positional stream; are the resulting position-carrying Key and Query vectors.

The final attention score for head simply adds the two streams together:

The content path keeps all of MLA’s speed benefits untouched; the position path carries all the positional signal, cached separately (a small extra cost, but unavoidable and cheap compared to the savings from MLA itself).

Main idea: decouple what a token means (compressed, RoPE-free) from where a token is (small, dedicated, RoPE-carrying) — so each half can be optimized on its own terms.

Partial RoPE

Even within the small position stream, rotating every dimension is more compute than necessary. Partial RoPE rotates only the first dimensions, leaving the rest untouched:

where: is the number of leading dimensions that get RoPE applied; is the total dimension of the vector; means “stitched back together into one vector.”

For example, with , RoPE might rotate only dimensions 1–32 and leave 33–128 exactly as they were.

Why this is enough: position doesn’t need to permeate the entire vector to be recoverable — a compact “positional footprint” in a subset of dimensions carries all the signal the attention score needs.

Benefits: fewer sine/cosine computations per token, less memory traffic moving rotated values around, and the untouched dimensions stay purely content-based with zero positional interference.

Analogy: you don’t need to stamp a room number on every single page of a book. One sticky note at the front is enough — the rest of the pages are free to just be content.

3.7 — Sparse Attention for Long Sequences

The Quadratic Cost Problem

Standard attention computes a full score matrix (“What the QK Transpose Matrix Looks Like” (Section 3.1)), which costs in sequence length . At tokens, that matrix has entries — computationally infeasible to form in full.

Main idea: if you can’t afford to let every token look at every other token, the fix is to make each token look at fewer tokens — either a fixed nearby window, or a smartly chosen subset. Sections 7.2–7.4 cover both strategies.

Sliding Window Attention (Longformer / SWA)

Idea: restrict each token to only attend within a fixed local window of size :

where: is the window radius — how many tokens on each side a token is allowed to see.

This produces a banded attention matrix — only a diagonal strip is ever filled in, cutting cost to:

The receptive field trick (used in Mistral): although any single layer only sees neighbors, stacking layers lets information hop from neighbor to neighbor to neighbor, so the effective receptive field after layers grows to roughly — like gossip spreading through a social network, one hop at a time.

Limitation: a genuinely important token sitting 100,000 positions away will simply never fall inside any window, no matter how many layers you stack.

Longformer: Local and Global Tokens

Longformer’s hybrid fix: keep sliding-window attention for most tokens, but designate a handful of global tokens (e.g., a [CLS] token) that attend to — and are attended to by — everyone, with full unrestricted attention.

Full attention versus sliding-window attention versus Longformer’s window-plus-global pattern.

This gives cheap local context for most tokens, plus a small number of “broadcast hubs” that let global information flow anywhere — without ever paying the full cost.

DeepSeek Sparse Attention (DSA)

The gap Longformer can’t close: what if the one truly relevant token sits at position 700,000, while the current token is at position 1,000,000, and there’s no global-token mechanism watching that specific spot? A fixed window and a handful of hand-picked global tokens simply miss it.

DSA’s answer: don’t fix the window in advance — dynamically pick out the most relevant tokens for each query, wherever they happen to be.

The Lightning Indexer

A cheap, lightweight, MQA-style attention pass whose only job is to estimate relevance before the real, expensive attention runs:

where:

  • — a lightweight query projection for the current token, separate from the main attention’s Query.
  • — a single shared Key (MQA-style — one Key for all heads, so this pass is cheap) representing token for indexing purposes only.
  • — zeroes out any negative score, so clearly-irrelevant tokens get exactly zero and are dropped from consideration rather than merely down-weighted.

Quantization + Hadamard Rotation

To make the indexer even cheaper, its vectors are stored in INT8 (8-bit integers) instead of FP16 — roughly a compute reduction.

The catch: naive quantization struggles with vectors that have a huge dynamic range, e.g.  — the tiny values get crushed to zero once everything is rescaled to fit INT8’s limited range.

The fix: apply a Hadamard transform before quantizing. A Hadamard matrix contains only s and s:

where: are Hadamard matrices of size 2 and 4 respectively — used to “mix” a vector’s entries before quantizing it.

Key property: — a Hadamard matrix is orthogonal, meaning it acts purely as a rotation (it doesn’t stretch or shrink vectors, just reorients them).

Effect on the vector: a spiky vector like becomes a flat after the Hadamard transform — the same total “energy,” but now spread evenly across all dimensions, so no single value dominates and quantization preserves everything accurately.

Why rotating first doesn’t change the final answer:

where: is the identity matrix. Because is orthogonal, rotating both the Query and Key by the same leaves their dot product completely unchanged — so this is a pure numerical-stability trick with zero effect on the actual attention math.

The Full DSA Pipeline

Net result: roughly 2–3× faster processing on long sequences, 30–40% memory reduction, and negligible loss in output quality — because the cheap Lightning Indexer only decides which tokens matter; the actual attention computation on the selected tokens still runs at full precision and quality.

3.8 — Layer Normalization

What It Is and Where It Lives

Layer Normalization sits at the “Add & Norm” blocks of the transformer — once right after multi-head attention, and once right after the feed-forward network, in every layer.

Main idea: as data flows through many stacked layers, activation values can drift to very large or very small magnitudes, destabilizing training. Layer Norm re-centers and re-scales each token’s activation vector back to a consistent, healthy range at every layer.

The Formula

For a single token’s activation vector :

where:

  • — the mean of ’s entries (computed across the feature dimension, for this one token).
  • — the variance of ’s entries.
  • — after being re-centered (subtract ) and re-scaled (divide by standard deviation) — now has mean 0 and unit variance.
  • — learned per-dimension scale and shift parameters, letting the network re-introduce whatever scale/offset it actually needs after normalizing.
  • — a tiny constant (around ) added purely to avoid dividing by zero.

Contrast with Batch Normalization: BatchNorm computes across the batch dimension (across different examples); LayerNorm computes them across the feature dimension, independently for each token. This makes LayerNorm indifferent to batch size and sequence length — a good fit for NLP, where sequences are variable-length and batches are sometimes small.

Post-LN vs Pre-LN

Post-LN (the original Transformer design): normalize after adding the residual:

Post-LN normalises after the residual add; Pre-LN normalises inside the branch.

Pre-LN (today’s default): normalize before the sublayer even runs:

where: is the residual stream entering layer ; is either the attention block or the feed-forward block.

Pre-LN trains more stably, especially at large scale, because the raw residual stream flows straight through the network unnormalized, keeping gradients well-behaved. Post-LN, by contrast, can suffer from training instability in very deep networks.

RMSNorm: The Modern Variant

RMSNorm (Zhang et al., 2019) simplifies LayerNorm by dropping the mean-centering step entirely — it normalizes only by the root-mean-square magnitude:

where: measures the overall magnitude of without first subtracting a mean; is still a learned per-dimension scale, but there’s no learned shift this time.

No mean subtraction, no bias term — fewer operations, fewer parameters, faster in practice. Used in LLaMA, Mistral, and most modern LLMs, almost always paired with Pre-LN.

3.9 — Synthesis: How It All Fits Together

The Modern Transformer Layer

A single transformer layer in a modern LLM (LLaMA-style) chains these steps:

One modern layer: pre-norm, RMSNorm, RoPE attention and a gated feed-forward network, repeated L times.
  1. RMSNorm (Pre-LN)
  2. Multi-Head Attention with RoPE applied to Q and K
  3. Residual add
  4. RMSNorm (Pre-LN)
  5. Feed-Forward Network
  6. Residual add

Step 2’s attention block typically uses GQA (or MLA, in DeepSeek’s models) for KV cache efficiency — the two efficiency ideas (positional encoding choice, and KV-cache-saving attention variant) are independent and simply stacked together.

The Position Information Flow

Token embedding x_m
         |
         + (pure word meaning — no position yet)
         |
    [Attention layer]
         |
    Apply RoPE to Q and K:
         q_m' = R(m*theta) q_m
         k_n' = R(n*theta) k_n
         |
    Dot product:
         q_m' . k_n' = f(m - n)   <- only relative distance!
         |
    Attention weights + Value aggregation
         |
    Output (now position-aware)

Position is injected inside the attention layer, not at the input. The word embedding itself stays purely about meaning; geometry (position) is handled entirely by the attention mechanism.

The KV Efficiency Hierarchy

Method Cache Size Quality Notes
MHA Best Baseline — every head keeps its own full K/V
GQA ( groups) Very good Groups of heads share K/V — used in LLaMA 2+
MQA Good All heads share one K/V — aggressive sharing
MLA , with Excellent Compress K/V into a small latent — DeepSeek

where: is sequence length; is head count; is per-head K/V dimension; is the number of GQA groups; is MLA’s latent dimension.

The Positional Encoding Hierarchy

Method Type Relative? Learned? Extrapolates? Modern Use
Sinusoidal Absolute, additive Approximate No Yes Original Transformer
Learned absolute Absolute, additive No Yes No GPT-2, BERT
T5 Bias Relative, added to score Yes Yes () Partial T5 family
ALiBi Relative, added to score Yes No Yes BLOOM, MPT
RoPE Relative, multiplicative on Q/K Yes No Yes LLaMA, Mistral, DeepSeek

3.10 — Quick Reference: Key Equations

Attention

Sinusoidal PE

ALiBi

RoPE (2D block for pair i)

MLA Compression

Layer Normalization