You’ll learn how residual connections carry an input around a transformation and how layer normalization controls the scale of each token’s vector. These two operations will help us assemble a transformer after the Attention chapter. A preview of that block is available below for readers returning to this page.
Why Do We Need These?
As we stack more layers, two problems can make training difficult:
Activation scale: Values can grow or shrink as each layer transforms them.
Gradient flow: Repeated transformations can shrink the learning signal that reaches early layers.
Residual connections provide a direct path for the signal. Layer normalization controls the values presented to a transformation. Both help deep networks train.
Residual Connections
The problem: gradients vanish in deep networks
In a deep network, the gradient must flow backward through every layer’s transformation. If each layer shrinks the gradient even slightly (say by a factor of 0.9), the signal disappears fast. It’s the same vanishing gradient problem we saw with RNNs, but across layers instead of across time.
Toggle between “With Residuals” and “Without Residuals” below. Try increasing the layer count to see how the problem compounds:
Gradient Flow Through Layers
Gradient Magnitude
0.99
L1
1.02
L2
1.01
L3
1.02
L4
1.03
L5
0.99
L6
1.02
L7
1.00
L8
1.02
L9
0.96
L10
1.00
Out
✅ With residual connections: Gradients flow freely through the "+" shortcut. Even with 10 layers, the gradient at layer 1 is 0.99 — the model can learn!
What to look for: In “Without Residuals” mode, watch the bars shrink from right to left. Now switch to “With Residuals” and compare the earlier layers. The shortcut gives gradients a direct route around a transformation; this helps preserve the signal, but does not guarantee that every deep network trains successfully.
The gradient through a deep network is a product of each layer’s derivative:
∂input∂output=fN′⋅fN−1′⋅…⋅f1′
If each fi′ is slightly less than 1, the product vanishes exponentially. For example, 0.950≈0.005.
The solution: add a shortcut
The fix is surprisingly simple. Instead of replacing the input with the layer’s output, we add the layer’s output to the original input:
Analogy: Think of a highway with an express lane. Normal traffic (the gradient) must pass through every toll booth (layer transformation), losing speed each time. A residual connection adds an express lane that bypasses all booths. Even if the toll booths grind traffic to a halt, the express lane guarantees flow. Where the analogy breaks: unlike a real highway with separate lanes, the residual adds the express-lane signal and the transformed signal together, so the layer’s contribution isn’t lost.
Concrete example: Suppose the input vector is [1.0, 2.0] and the layer transforms it to [0.1, 0.3]:
Without residual: output = [0.1, 0.3] (layer’s transformation replaced the input)
With residual: output = [1.0 + 0.1, 2.0 + 0.3] = [1.1, 2.3] (original input preserved, layer adds a small adjustment)
The gradient through x + f(x) is 1 + f'(x). Even if f'(x) is tiny, the gradient is still approximately 1.
output=x+f(x)
The gradient through this operation is:
∂x∂(x+f(x))=1+∂x∂f
Even if ∂x∂f is tiny, the gradient is still approximately 1! The identity connection creates a highway for gradients to flow back unimpeded.
🤔Quick Check
What would happen if you trained a 50-layer transformer without residual connections?
Your turn
Choose an answer to check your understanding.
Try another option
Think about what happens when you multiply 0.9 by itself 50 times. How much of the original gradient reaches layer 1?
Correct!
Without residual connections, gradients are multiplied through 50 layers of transformations. Even if each layer preserves 90% of the gradient (0.9), after 50 layers: 0.9^50 ≈ 0.005, only 0.5% of the gradient reaches layer 1. The early layers are practically frozen.
Answer: C
Without residual connections, gradients are multiplied through 50 layers of transformations. Even if each layer preserves 90% of the gradient (0.9), after 50 layers: 0.9^50 ≈ 0.005, only 0.5% of the gradient reaches layer 1. The early layers are practically frozen.
Attempts: 0
Layer Normalization
The problem: activations drift and explode
Residual connections fix gradient flow backward. But there’s a separate problem going forward: as activations pass through layer after layer, their distribution shifts. Early layers might output values centered around 0 with a standard deviation of 1. But by layer 10, the mean could be 87 and the standard deviation 4312. Later layers must constantly adapt to a moving target, and eventually the numbers overflow entirely.
Toggle “No Normalization” vs “With LayerNorm” below. Increase the layer count and watch what happens to the standard deviation:
Activation Statistics Across Layers
Standard Deviation (σ)
1.00
In
1.58
L1
1.61
L2
2.03
L3
3.18
L4
4.47
L5
4.94
L6
6.71
L7
10.1
L8
14.6
L9
16.2
Out
Mean (μ)
0.10
In
1.58
L1
2.28
L2
2.83
L3
4.19
L4
3.61
L5
4.96
L6
7.65
L7
11.2
L8
10.9
L9
21.7
Out
Without normalization: Each layer's output shifts and scales the distribution further. After 10 layers, std has grown to 16.2. Activations are drifting. Training will be slow and unstable.
What to look for: Without normalization, the σ bars grow exponentially. With 15+ layers, values explode past 100. Now switch to “With LayerNorm” and notice every layer stays near σ = 1.0, no matter how many layers you add.
See the normalization steps
Now that you’ve seen why we need normalization, here’s how it works. Click through the tabs to see each step. Adjust γ and β to see how the learned parameters affect the final output:
Layer Normalization Step by Step
Raw activations (range: -3.0 to 2.2)
d0
-2.95
d1
-1.15
d2
1.31
d3
-1.40
d4
-1.97
d5
1.31
d6
2.24
d7
-1.57
μ = -0.522σ = 1.753
LayerNorm(x) = γ · (x − μ) / σ + β
What to look for: Watch the μ and σ stats at the bottom. After step 2 (“Centered”), μ drops to 0. After step 3 (“Normalized”), σ becomes 1. The final step lets the network learn whatever scale and shift it needs, but starting from that stable baseline.
How it works
Layer normalization takes each vector and re-centers it to have a mean of 0 and a standard deviation of 1. Then it applies a learned scale (γ) and shift (β) so the network can still represent whatever distribution it needs.
Concrete example: Suppose a token’s activation vector after layer 5 is [2, −3, 1, 4].
Scale + shift: The network learns γ and β. If γ = [2, 2, 2, 2] and β = [0.5, 0.5, 0.5, 0.5]: output = [1.28, −2.64, 0.5, 2.86]
No matter how wild the input was (mean 87, std 4312 at layer 10), normalization resets it to a predictable range. The learned scale and shift give the network flexibility to represent whatever distribution it actually needs, but starting from a stable baseline.
LayerNorm(x)=γ⊙σ2+ϵx−μ+β
where:
μ=d1∑ixi (mean of the vector)
σ2=d1∑i(xi−μ)2 (variance)
γ,β are learnable parameters (scale and shift)
ϵ is a small constant (e.g., 10−6) for numerical stability
Why does layer normalization use learnable γ and β parameters instead of just normalizing to mean 0, std 1?
Your turn
Choose an answer to check your understanding.
Try another option
Think about what would happen if every layer was forced to output values in exactly the same range. Could the network represent diverse patterns?
Correct!
Without γ and β, every layer would be forced into the same narrow distribution. The learned parameters let each layer choose its own scale and shift: maybe one layer needs values in [-10, 10] while another works best near [0, 1]. Normalization provides the stable starting point; γ and β provide the flexibility.
Answer: B
Without γ and β, every layer would be forced into the same narrow distribution. The learned parameters let each layer choose its own scale and shift: maybe one layer needs values in [-10, 10] while another works best near [0, 1]. Normalization provides the stable starting point; γ and β provide the flexibility.
Attempts: 0
Why not batch normalization?
You might know Batch Normalization from CNNs. It normalizes across the batch dimension (across different examples). But for transformers, that doesn’t work:
Aspect
BatchNorm
LayerNorm
Normalizes across
Batch (examples)
Features (dimensions)
Requires
Large batch size
Works with any batch size
At inference
Needs running statistics
No extra state needed
For sequences
Problematic (variable length)
Works naturally
The key reason: transformers process sequences of different lengths. For a batch where some sequences are 10 tokens and others are 100, what does “position 50” even mean for the short sequences? LayerNorm sidesteps this entirely by normalizing each token independently, within its own dimensions.
The next chapter introduces attention, and Architecture Overview introduces the feed-forward network (FFN). On a first pass, continue to the summary below. This preview shows where today’s two operations will fit once you have learned those components.
Every transformer block uses both tricks. Toggle between Pre-LN (modern) and Post-LN (original) to see the difference. Click “Animate” to watch data flow through the block:
Click any block for details
Input / Output
Layer Norm
Transform (Attn / FFN)
Residual Add
Residual arc: carries the original signal around the transform
Pre-LN (GPT-2, LLaMA): Normalize before each transform. The residual path stays clean, making training stable without warmup.
What to look for: In Pre-LN mode, notice that LayerNorm comes before each sublayer (Attention, FFN). The residual connections (dashed arrows) skip around the normalize-then-transform pair. In Post-LN mode, the sublayer operates on raw, un-normalized values, and normalization happens after the residual add.
Pre-LN vs Post-LN
Why does ordering matter? Pre-LN normalizes the input before it enters the sublayer, so every transformation starts from a stable baseline. Post-LN normalizes after the sublayer, meaning the transformation itself can produce wild values. With 96 layers, that instability compounds.
Pre-LN is like setting the scale of an instrument before each measurement. This analogy describes the order of operations; normalization does not guarantee a good prediction or a stable optimizer step.
Pre-LN (modern)
Post-LN (original)
Order
LN → Sublayer → Add
Sublayer → Add → LN
Stability
More stable
Less stable
Warmup
Depends on the training setup
Often helps with stability
Used by
GPT-2, GPT-3, LLaMA
Original Transformer, BERT
x′=x+Attention(LN(x))output=x′+FFN(LN(x′))
class TransformerBlock: def __init__(self, d_model, n_heads, d_ff): self.attn = MultiHeadAttention(d_model, n_heads) self.ffn = FeedForward(d_model, d_ff) self.ln1 = LayerNorm(d_model) self.ln2 = LayerNorm(d_model) def forward(self, x, mask=None): # Sub-layer 1: Attention with residual + norm x = x + self.attn(self.ln1(x), mask) # Sub-layer 2: FFN with residual + norm x = x + self.ffn(self.ln2(x)) return x
Formula
RMSNorm(x)=d1∑ixi2+ϵx⋅γ
RMSNorm skips the mean subtraction. It only normalizes by the root-mean-square. No bias parameter either.
Why use it? About 10% faster than LayerNorm (one fewer operation), and empirically works just as well.
Gives the signal and gradients a direct path around a transformation
Layer Normalization
Center and normalize each vector, then learn a scale and shift
Controls activation scale
Together
Wrap the transformations inside a transformer block
Help deeper networks train
Residual Connection
output=x+sublayer(x)
Layer Normalization
LN(x)=γ⊙σ2+ϵx−μ+β
Pre-LN Transformer Block
x′=x+Attention(LN(x))output=x′+FFN(LN(x′))
Test Your Understanding
✍️Fill in the Blanks
Residual connections add the sublayer output to the original , creating a shortcut that helps reduce gradients.
Fill in every blank, then check your answer.
A blank is still empty.
Fill in every blank before checking your answer.
Not quite.
Try another answer, or reveal the solution.
Correct.
One accepted answer is shown in each blank.
Answer revealed.
The blanks now show the answers.
What we skipped on this page:
Residual connections. He et al., “Deep Residual Learning for Image Recognition” (2015) introduced skip connections for CNNs, enabling networks with 100+ layers. The same principle directly carries over to transformers: without residual connections, GPT-3’s 96 layers would be untrainable.
Layer normalization. Ba, Kiros & Hinton, “Layer Normalization” (2016) proposed normalizing across the feature dimension instead of the batch dimension. This avoids batch normalization’s dependence on batch size and its issues with variable-length sequences.
Pre-LN stability. Xiong et al., “On Layer Normalization in the Transformer Architecture” (2020) showed that Pre-LN transformers have well-behaved gradients at initialization, explaining why they train stably without learning rate warmup. Post-LN requires careful warmup because the expected gradient norm grows with depth at initialization.
RMSNorm. Zhang & Sennrich, “Root Mean Square Layer Normalization” (2019) showed that the mean-centering step in LayerNorm is not essential. RMSNorm removes it, saving computation while matching performance. Now standard in LLaMA, Gemma, and Mistral.
Learning Checklist
I can explain why deep networks need residual connections and what happens without them
I understand how output = x + f(x) preserves gradient flow
I can walk through the layer normalization steps (center, normalize, scale + shift) with real numbers
I know why transformers use LayerNorm instead of BatchNorm
I can explain the different jobs of a residual connection and normalization
I can describe why these operations help training without guaranteeing that every gradient stays large
What’s Next
We have vectors, sequence memory, and ways to keep deep transformations trainable. Next, each token will gather information directly from other tokens to update its representation.