GPT-2 › Worked Example: Tracing a Forward Pass

Michael BrenndoerferUpdated July 24, 20254 min read
Language AI HandbookAll chapters
Part 28 of 67GPT Architecture
Chapter 198GPT-2 › Worked Example: Tracing a Forward Pass
Reading section 7 of 11 · Worked Example: Tracing a Forward Pass · 4 minSection 7 of 11 · 4 min

Book contents

Section 7 of 11 · 4 min read

GPT-2 › Worked Example: Tracing a Forward PassOne section · Sections in this chapter7 / 11 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

To solidify your understanding of how GPT-2 processes text, let's trace a minimal forward pass step by step with concrete dimensions. We'll use GPT-2 Small as our example, with hidden size dmodel=768d_{model} = 768, 12 layers, and 12 attention heads.

Suppose the input is the sequence "The cat sat", which tokenizes to 3 tokens with indices, say, [464, 3797, 3332].

Step 1: Token Embedding Lookup. We look up each token index in the token embedding table, which has shape (50257,768)(50257, 768). For 3 tokens, we retrieve a matrix of shape (3,768)(3, 768). Each row is the 768-dimensional representation of that token.

Step 2: Position Embedding Lookup. We look up positions 0, 1, 2 in the position embedding table, also of shape (1024,768)(1024, 768). We retrieve another (3,768)(3, 768) matrix. Adding token embeddings and position embeddings gives the initial hidden state x0x_0 of shape (3,768)(3, 768).

Step 3: Pre-Norm Attention in Layer 1. We apply LayerNorm to x0x_0, creating x^0\hat{x}_0 of shape (3,768)(3, 768) with mean 0 and variance 1 per position. We then project x^0\hat{x}_0 through the combined QKVQKV projection matrix of shape (768,2304)(768, 2304) to get a (3,2304)(3, 2304) matrix, which we split into three (3,768)(3, 768) matrices for QQ, KK, and VV.

Step 4: Multi-Head Attention Split. We reshape each of QQ, KK, and VV from (3,768)(3, 768) into (12,3,64)(12, 3, 64) by splitting the 768 dimensions across 12 heads of 64 dimensions each. For head hh, the query matrix is QhQ_h of shape (3,64)(3, 64), and similarly for KhK_h and VhV_h.

Step 5: Scaled Dot-Product Attention. For each head hh, we compute attention scores and weighted values:

Ah=softmax(QhKhT64)VhA_h = \text{softmax}\left(\frac{Q_h K_h^T}{\sqrt{64}}\right) V_h

where:

  • QhKhTQ_h K_h^T has shape (3,3)(3, 3): a score matrix where entry (i,j)(i,j) measures how much position ii should attend to position jj
  • 64=8\sqrt{64} = 8: the scaling factor preventing large dot products from saturating the softmax
  • The causal mask zeroes out the upper triangle: position 0 only attends to itself, position 1 attends to positions 0 and 1, position 2 attends to all three

The output AhA_h has shape (3,64)(3, 64).

Step 6: Concatenate and Project. We concatenate the 12 head outputs to get a (3,768)(3, 768) matrix, then project through the output projection of shape (768,768)(768, 768), giving a (3,768)(3, 768) attention output.

Step 7: First Residual Addition. We add the attention output to the original x0x_0: x1=x0+attn_outputx_1 = x_0 + \text{attn\_output}. Both have shape (3,768)(3, 768). The residual connection preserves the original information while the attention output adds what the attention mechanism learned.

Step 8: Pre-Norm Feed-Forward. We apply LayerNorm to x1x_1, then pass through the feed-forward network. The first linear layer expands from 768 to 3072 dimensions, GELU activation is applied, and the second linear layer compresses back to 768. The result has shape (3,768)(3, 768).

Step 9: Second Residual Addition. We add the feed-forward output to x1x_1: x2=x1+ffn_outputx_2 = x_1 + \text{ffn\_output}. This completes one transformer block.

Steps 10 through 21: Repeat for layers 2 through 12. The (3,768)(3, 768) hidden state passes through 11 more identical blocks. Each adds its learned transformations via residual connections, progressively enriching each token's representation with broader context.

Step 22: Final LayerNorm. After all 12 layers, we apply the final layer normalization to the (3,768)(3, 768) output.

Step 23: Logit Projection. We multiply by the transposed token embedding matrix of shape (768,50257)(768, 50257), creating logits of shape (3,50257)(3, 50257). For next-token prediction, we take the last position's logits (shape (50257,)(50257,)) and sample from this distribution to generate the 4th token.

This entire forward pass computes all three positions simultaneously during training, with the causal mask so each position only uses information from prior positions. The efficiency comes from this parallel computation: rather than running the model three times sequentially to train on positions 1, 2, and 3, we train on all positions in a single forward pass.