Why This Guide Exists
Every AI breakthrough you've heard of - ChatGPT, Claude, Gemini, GPT-5, Stable Diffusion - is built on Transformers.
Yet most explanations either:
- •Dump formulas without intuition
- •Stay surface-level without going deep
- •Skip the "why" behind each component
This guide is different. By the end, you'll understand Transformers so deeply you can explain them from scratch, reason about why they work, and teach others confidently.
Prerequisites: Basic Python. Some familiarity with neural networks helps but isn't required.
Part 1: The Big Picture
What Problem Led to Transformers?
Imagine you're translating this sentence:
"The cat sat on the mat because it was tired."
What does "it" refer to? The cat, obviously. But how do you know?
Because you understand that:
- 1"Cat" is the subject doing an action
- 2"Tired" is a state that applies to living things
- 3"Mat" doesn't get tired
- 4The sentence structure connects "it" back to "cat"
This is the core challenge of language understanding: connecting related pieces of information across a sequence.
Before Transformers, we used RNNs (Recurrent Neural Networks) and LSTMs:
RNN Processing:
[The] → [cat] → [sat] → [on] → [the] → [mat] → [because] → [it] → [was] → [tired]
↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓ ↓
h1 → h2 → h3 → h4 → h5 → h6 → h7 → h8 → h9 → h10
The problem: By the time we reach "it", the information about "cat" has passed through 7 steps. It gets diluted, like a game of telephone.
The Transformer solution: What if every word could directly look at every other word?
Transformer Processing:
The cat sat on the mat because it was tired
↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑ ↑
└─────┴─────┴─────┴───�����─┴─────┴───────┴───────┴──────┴──────┘
ALL WORDS SEE ALL WORDS
(through attention)
When processing "it", the model can directly look at "cat" and "mat", compute which is more relevant, and use that information. No telephone game.
First Mental Model: The Transformer as a Reading Group
Imagine a reading group analyzing a book. In the old approach (RNN), each person reads one chapter, then summarizes it for the next person. By chapter 10, the summary of chapter 1 is vague.
In the Transformer approach, everyone sits in a circle with the full book. When discussing chapter 10, anyone can say "let me check chapter 1" and directly look it up.
That's attention: the ability to directly access any part of the input when processing any other part.
The Transformer as a Data Flow Pipeline
Part 2: Foundations Before Architecture
Tokens: The Atoms of Language
A token is the smallest unit the model works with. It's not always a word.
Input: "unhappiness"
Tokens: ["un", "happiness"] // Subword tokenization
Input: "ChatGPT is amazing!"
Tokens: ["Chat", "GPT", " is", " amazing", "!"]
Why tokenize this way?
- •Handles rare words ("unhappiness" might be rare, but "un" and "happiness" are common)
- •Handles new words (the model has never seen "ChatGPT" but knows "Chat" and "GPT")
- •Fixed vocabulary size (typically 50K-100K tokens)
Analogy: Like how written Chinese uses characters that combine into words, tokenization breaks language into reusable pieces.
Embeddings: Giving Words Meaning
An embedding is a list of numbers (vector) that represents a token's meaning.
"king" → [0.2, 0.8, 0.1, 0.5, ...] // 768 or more numbers
"queen" → [0.25, 0.75, 0.15, 0.48, ...] // Similar because related meaning
"banana" → [0.9, 0.1, 0.7, 0.2, ...] // Different because different concept
The magic: These vectors capture relationships!
king - man + woman ≈ queen
Paris - France + Italy ≈ Rome
Intuition: Think of each number as measuring something about the word. Maybe position 1 measures "royalty", position 2 measures "gender", position 3 measures "living thing". The model learns what to put in each position.
What would break without embeddings? The model would only see token IDs like [42, 891, 23, ...]. It would have no sense of meaning or similarity. "dog" and "puppy" would be as different as "dog" and "quantum".
Query, Key, Value: The Heart of Attention
This is the most important concept. Let's build intuition carefully.
Analogy: The Library Search
Imagine you're in a library looking for information about "machine learning applications in healthcare."
- •Query (Q): Your search question - "machine learning healthcare applications"
- •Keys (K): The titles/summaries of every book - "ML in Medicine", "Deep Learning Basics", "Healthcare AI"
- •Values (V): The actual content of the books
The search process:
- 1Compare your Query against all Keys (titles)
- 2Find which Keys match best (relevance scores)
- 3Retrieve the Values (content) from the matching books
- 4Combine them based on relevance
In attention:
- •Each word generates a Query: "What information am I looking for?"
- •Each word generates a Key: "What information do I contain?"
- •Each word generates a Value: "Here's my actual information"
Sentence: "The cat sat on the mat because it was tired"
When processing "it":
Query of "it": "I need to find what I refer to"
Keys of each word:
"cat": "I'm a noun, a subject, an animal"
"mat": "I'm a noun, an object, not alive"
"tired": "I'm an adjective describing living things"
Attention scores: "it" → "cat" = HIGH (living thing, subject)
"it" → "mat" = LOW (object, not alive)
Result: "it" gets information primarily from "cat"
Part 3: Self-Attention Step by Step
Let's walk through self-attention with a concrete example.
Step 1: Start with Embeddings
# Simplified example with dimension 4 (real models use 768+)
sentence = ["I", "love", "AI"]
embeddings = {
"I": [1.0, 0.0, 0.0, 0.5],
"love": [0.0, 1.0, 0.5, 0.0],
"AI": [0.0, 0.5, 1.0, 0.0]
}
# Stack into matrix X (3 tokens × 4 dimensions)
X = [[1.0, 0.0, 0.0, 0.5], # "I"
[0.0, 1.0, 0.5, 0.0], # "love"
[0.0, 0.5, 1.0, 0.0]] # "AI"
Step 2: Create Query, Key, Value Vectors
Each token creates three vectors by multiplying with learned weight matrices:
Q = X × W_q (What am I looking for?)
K = X × W_k (What do I represent?)
V = X × W_v (What information do I carry?)
# Weight matrices are learned during training
W_q = [[...], [...], [...], [...]] # 4×4 matrix
W_k = [[...], [...], [...], [...]]
W_v = [[...], [...], [...], [...]]
# After multiplication:
Q = [
[0.5, 0.2, 0.8, 0.1], # Query for "I"
[0.3, 0.7, 0.2, 0.4], # Query for "love"
[0.1, 0.5, 0.9, 0.3] # Query for "AI"
]
# (similar for K and V)
Why three separate transformations?
- •Q, K, V serve different purposes
- •Learned weights let the model decide what questions to ask (Q), what to advertise (K), and what to share (V)
- •Without this separation, attention would just compare raw embeddings
Step 3: Compute Attention Scores
For each token, compare its Query with all Keys:
Scores = Q × K^T (dot product measures similarity)
K for "I" K for "love" K for "AI"
Q for "I" 0.8 0.3 0.2
Q for "love" 0.2 0.9 0.6
Q for "AI" 0.1 0.5 0.95
Intuition:
- •"I"'s query matches well with "I"'s key (0.8)
- •"love"'s query matches best with "love"'s key (0.9) but also with "AI" (0.6)
- •"AI"'s query strongly matches "AI"'s key (0.95)
Step 4: Scale the Scores
Scaled_Scores = Scores / sqrt(d_k)
If d_k = 4: Scaled_Scores = Scores / 2
Why scale?
- •Without scaling, large dimension vectors produce large dot products
- •Large values cause softmax to become "spiky" (nearly one-hot)
- •Spiky softmax = unstable gradients during training
- •Scaling keeps values in a good range
What breaks if removed? Training becomes unstable. The model either pays 100% attention to one token or attention becomes random noise.
Step 5: Apply Softmax
Convert scores to probabilities (must sum to 1):
Attention_Weights = softmax(Scaled_Scores)
"I" "love" "AI"
Attention for "I": 0.65 0.20 0.15 (sums to 1.0)
Attention for "love": 0.15 0.50 0.35 (sums to 1.0)
Attention for "AI": 0.10 0.25 0.65 (sums to 1.0)
Intuition: These are "how much attention to pay" weights. "I" pays 65% attention to itself, 20% to "love", 15% to "AI".
Step 6: Weighted Sum of Values
Multiply attention weights by Values to get final output:
Output = Attention_Weights × V
For "I":
Output = 0.65 × V["I"] + 0.20 × V["love"] + 0.15 × V["AI"]
Result: Each token's output is a weighted combination of ALL tokens' values, weighted by relevance.
This is the core insight: After self-attention, "I" isn't just "I" anymore. It's "I-in-the-context-of-love-and-AI". Each token becomes context-aware.
Part 4: Multi-Head Attention
Why One Attention Head Isn't Enough
Single attention can only capture one relationship pattern at a time. But language has many simultaneous patterns:
- •Syntactic: "The cat that chased the mouse..."
- •Semantic: "The doctor treated the patient"
- •Positional: "First... then... finally"
- •Coreference: "John said he would..."
Solution: Run multiple attention operations in parallel (multiple "heads"), each learning different patterns.
Implementation
class MultiHeadAttention:
def __init__(self, d_model=512, num_heads=8):
self.num_heads = num_heads
self.d_k = d_model // num_heads # 512/8 = 64 per head
# Each head has its own Q, K, V projections
self.W_q = [Linear(d_model, self.d_k) for _ in range(num_heads)]
self.W_k = [Linear(d_model, self.d_k) for _ in range(num_heads)]
self.W_v = [Linear(d_model, self.d_k) for _ in range(num_heads)]
# Final projection after concatenation
self.W_o = Linear(d_model, d_model)
def forward(self, x):
head_outputs = []
for i in range(self.num_heads):
Q = self.W_q[i](x)
K = self.W_k[i](x)
V = self.W_v[i](x)
# Standard attention
scores = Q @ K.T / sqrt(self.d_k)
weights = softmax(scores)
output = weights @ V
head_outputs.append(output)
# Concatenate all heads
concatenated = concat(head_outputs, axis=-1) # Back to d_model size
# Final linear transformation
return self.W_o(concatenated)
What different heads learn (observed in trained models):
- •Head 1: Subject-verb relationships
- •Head 2: Adjective-noun relationships
- •Head 3: Positional patterns (nearby words)
- •Head 4: Long-range dependencies
- •Head 5: Punctuation and structure
- •Head 6: Named entity relationships
- •Head 7: Semantic similarity
- •Head 8: Syntactic roles
Part 5: Positional Encoding
The Problem
Self-attention has no concept of order. To attention, these are identical:
"Dog bites man" → same attention patterns as → "Man bites dog"
The attention mechanism is permutation invariant - shuffle the words and you get the same result (with shuffled output).
But order matters in language!
The Solution: Add Position Information
Before attention, we add a position signal to each embedding:
final_embedding = word_embedding + positional_encoding
Sinusoidal Positional Encoding (Original Transformer)
def positional_encoding(position, d_model):
# Create encoding for one position
encoding = []
for i in range(d_model):
if i % 2 == 0:
# Even dimensions: use sine
encoding.append(sin(position / 10000^(i/d_model)))
else:
# Odd dimensions: use cosine
encoding.append(cos(position / 10000^((i-1)/d_model)))
return encoding
# Position 0: [sin(0), cos(0), sin(0), cos(0), ...]
# Position 1: [sin(1/10000^0), cos(1/10000^0), sin(1/10000^(2/512)), ...]
Why sine and cosine waves?
- 1Unique patterns: Each position gets a unique combination of values
- 2Relative positions: PE(pos+k) can be expressed as a linear function of PE(pos)
- 3Generalization: Works for sequences longer than training data
- 4Bounded values: Always between -1 and 1 (stable training)
Position 0: ▁▁▁▁▁▁▁▁ (flat wave)
Position 1: ▂▁▂▁▂▁▂▁ (slight variation)
Position 2: ▃▁▃▁▃▁▃▁ (more variation)
Position 10: ▆▁▆▁▆▁▆▁ (high variation in some dims)
Learned Positional Embeddings (Modern Approach)
class LearnedPositionalEmbedding:
def __init__(self, max_length=512, d_model=768):
# Just learn a vector for each position
self.embeddings = Parameter(shape=(max_length, d_model))
def forward(self, sequence_length):
return self.embeddings[:sequence_length]
Trade-off:
- •Learned: Better performance, but can't generalize beyond max_length
- •Sinusoidal: Slightly worse performance, but generalizes to any length
Part 6: The Full Transformer Architecture
---
## Part 7: Encoder Layer Deep Dive
Let's examine one encoder layer in detail.
### Component 1: Multi-Head Self-Attention
**What it does:** Lets each token gather information from all other tokens.
**Why it exists:** Language understanding requires context. "Bank" means different things in "river bank" vs "bank account".
**Failure if removed:** The model would process each word in isolation, unable to resolve ambiguity or understand relationships.
### Component 2: Add & Normalize (Residual Connection + Layer Norm)
# Layer normalization output = layer_norm(output)
**Why residual connection?**
- Deep networks suffer from vanishing gradients
- Residual connections provide a "highway" for gradients to flow backward
- The model can learn "just add a small adjustment" rather than "completely transform"
**Why layer normalization?**
- Keeps activation values in a reasonable range
- Stabilizes training
- Helps each layer work independently
**Failure if removed:**
- Without residual: Deep models won't train (gradients vanish)
- Without layer norm: Training is unstable, loss doesn't converge
### Component 3: Feed-Forward Network
**Why it exists:**
- Attention is good at mixing information between positions
- FFN is good at transforming information at each position
- The expansion (512 → 2048) provides more computation per position
**Analogy:** Attention is like a meeting where everyone shares information. FFN is like going back to your desk and thinking deeply about what you learned.
**Failure if removed:** The model can only linearly combine information. No non-linear transformations = limited expressiveness.
---
## Part 8: Decoder Layer Deep Dive
The decoder has everything the encoder has, plus two key differences.
### Difference 1: Masked Self-Attention
During generation, the decoder predicts one token at a time:
Position 3 shouldn't see positions 4, 5, 6... (they don't exist yet!)
**Masking ensures each position only attends to previous positions:**
### Difference 2: Cross-Attention
**The decoder needs to look at the encoder's output.**
In cross-attention:
- **Query** comes from the decoder (what we're generating)
- **Key, Value** come from the encoder (the input we're processing)
When generating "student": Decoder Q: "What English word should I generate here?" Encoder K/V: Information about "étudiant" Cross-attention: "student" attends strongly to "étudiant"
---
## Part 9: Training and Inference
### Training: Teacher Forcing
During training, we provide the correct output sequence:
The model predicts each token given previous CORRECT tokens.
### Inference: Autoregressive Generation
During inference, we generate one token at a time:
### Sampling Strategies
**Greedy:** Pick the highest probability token
- Simple but repetitive
**Temperature:** Scale logits before softmax
- Low temperature (0.1): More deterministic
- High temperature (1.5): More random/creative
**Top-k:** Only consider the k most likely tokens
**Top-p (Nucleus):** Consider tokens until cumulative probability reaches p
---
## Part 10: Transformer Variants
### Encoder-Only: BERT
Used for: Classification, NER, Question Answering
- Bidirectional: Every token sees every other token
- Pre-trained with masked language modeling
- Fine-tuned for specific tasks
### Decoder-Only: GPT
Used for: Text generation, Chatbots, Code completion
- Unidirectional: Each token only sees previous tokens
- Pre-trained with next token prediction
- ChatGPT, GPT-4, Claude are all decoder-only
### Encoder-Decoder: T5, BART
Used for: Translation, Summarization, Question Answering ```
- •Best for sequence-to-sequence tasks
- •Encoder understands input, decoder generates output
| Model Type | Attention Pattern | Best For |
|---|---|---|
| Encoder-only (BERT) | Bidirectional | Understanding tasks |
| Decoder-only (GPT) | Causal (left-to-right) | Generation tasks |
| Encoder-Decoder (T5) | Both | Sequence-to-sequence |
Part 11: Mathematical Summary
For those who want the formal equations:
Self-Attention
$$\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V$$
Where:
- •Q = XW_Q (queries)
- •K = XW_K (keys)
- •V = XW_V (values)
- •d_k = dimension of keys
Multi-Head Attention
$$\text{MultiHead}(Q, K, V) = \text{Concat}(head_1, ..., head_h)W^O$$
Where: $$head_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V)$$
Feed-Forward Network
$$\text{FFN}(x) = \max(0, xW_1 + b_1)W_2 + b_2$$
(ReLU activation, two linear transformations)
Layer Normalization
$$\text{LayerNorm}(x) = \gamma \cdot \frac{x - \mu}{\sigma + \epsilon} + \beta$$
Where μ, σ are mean and std of x, and γ, β are learned parameters.
Positional Encoding
$$PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$ $$PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)$$
Part 12: Key Takeaways
- 1Transformers enable direct connections between any two positions, solving the long-range dependency problem of RNNs.
- 2Attention is asking questions. Query asks, Key answers "I might be relevant", Value provides the information.
- 3Multi-head attention captures multiple relationship types simultaneously.
- 4Positional encoding is essential because attention alone is position-blind.
- 5The architecture is remarkably simple: Just attention + feed-forward + residuals + normalization, stacked many times.
- 6Scale matters. GPT-4 is the same architecture as the original Transformer, just bigger and trained on more data.
Explain Like I'm 12
Imagine you're reading a book with your friends. An old way (RNN) would be: each friend reads one page, then whispers what they remember to the next friend. By page 100, the whisper is garbled.
The Transformer way: Everyone has the whole book. When you're on page 100 and need to remember something from page 3, you just look it up directly. That's attention - looking up whatever you need, whenever you need it.
Explain Like I'm Preparing for ML Interviews
"Transformers use self-attention to compute representations where each token can attend to all other tokens in parallel. The attention mechanism computes query, key, and value projections, then uses scaled dot-product attention: softmax(QK^T/√d_k)V. Multi-head attention runs this in parallel h times with different projections to capture different relationship patterns. Combined with positional encoding, residual connections, layer normalization, and position-wise feed-forward networks, this forms the building block that's stacked to create the full architecture."
Follow-up prep:
- •Why scale by √d_k? (Prevents softmax from becoming too peaked, stabilizes gradients)
- •Why not just use attention? (FFN provides per-position transformation capacity)
- •Why residual connections? (Enable training of very deep networks)
- •Encoder vs decoder difference? (Masking in decoder prevents seeing future tokens)

