Skip to main content
Attention Mechanism

Attention Mechanism

The Bottleneck Problem

In the previous chapters, we built sequence-to-sequence models using encoder-decoder LSTMs. But there’s a fundamental problem: The entire source sequence is compressed into a single fixed-size vector. This is like asking someone to summarize a 300-page novel in a single tweet, and then expecting another person to reconstruct the entire plot from that tweet.
Encoder Bottleneck Problem

Evidence of the Problem


The Attention Solution

Intuition: Looking Back at the Source

Instead of forcing the decoder to use only the final encoder state, let it look at all encoder states and focus on relevant ones: When translating “dog” to “chien”:
  • Look at all encoder states
  • Focus attention on the state corresponding to “dog”
  • Use that information to generate “chien”
Key Insight: Attention computes a weighted combination of all encoder states, where weights indicate relevance to the current decoding step.

Attention Mechanisms in Detail

Dot-Product Attention

The simplest form of attention: Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right)V Why divide by dk\sqrt{d_k}? This is not an arbitrary choice — it is essential for numerical stability. When dkd_k is large (e.g., 512), each dot product qkq \cdot k is the sum of 512 terms. If entries of qq and kk have unit variance, the dot product has variance dkd_k (by the central limit theorem, the sum of 512 independent unit-variance terms has variance 512). So the raw scores have standard deviation dk22.6\sqrt{d_k} \approx 22.6. Softmax applied to values this large pushes almost all the probability mass onto a single key — the attention becomes a hard argmax, and its gradient effectively vanishes. Dividing by dk\sqrt{d_k} rescales the scores to unit variance, keeping the softmax in its “useful” regime where gradients flow to multiple keys. Without this scaling, training larger models would be dramatically harder. This is one of those small details that separates a paper implementation from a working one.

Visualizing Attention Weights

Attention Weight Visualization

Types of Attention

Additive (Bahdanau) Attention

The original attention mechanism from the 2014 paper: eij=vTtanh(W1hi+W2sj)e_{ij} = v^T \tanh(W_1 h_i + W_2 s_j) αij=exp(eij)kexp(ekj)\alpha_{ij} = \frac{\exp(e_{ij})}{\sum_k \exp(e_{kj})}

Multiplicative (Luong) Attention

Simpler and faster variants:

Self-Attention

Attending to the Same Sequence

Self-attention allows each position in a sequence to attend to all other positions:

Why Self-Attention Matters


Multi-Head Attention

Multiple Attention “Perspectives”

Instead of one attention function, use multiple “heads” that each learn different relationships: MultiHead(Q,K,V)=Concat(head1,...,headh)WO\text{MultiHead}(Q, K, V) = \text{Concat}(\text{head}_1, ..., \text{head}_h) W^O where headi=Attention(QWiQ,KWiK,VWiV)\text{where head}_i = \text{Attention}(QW_i^Q, KW_i^K, VW_i^V) Why multiple heads instead of one big attention? A single attention head can only compute one weighted average per query position — it assigns a single scalar relevance to each key. But language has multiple simultaneous relationships: “it” relates to “animal” syntactically (coreference), to “tired” semantically (attribute), and to “cross” structurally (subject-verb). Multiple heads let the model maintain all these relationships simultaneously, each head specializing in a different type of dependency. The mathematical cost is negligible: if dmodel=512d_{model} = 512 and you use 8 heads, each head operates in a dk=64d_k = 64 dimensional subspace. The total computation is the same as a single head with dk=512d_k = 512, but you get 8 independent attention patterns instead of 1. The output projection WOW^O then learns how to combine these perspectives. This is one of the best “free lunches” in deep learning architecture design.

Visualizing Multi-Head Attention

Multi-Head Attention Patterns

Positional Encoding

The Problem: Attention is Permutation-Invariant

Unlike RNNs, self-attention has no inherent notion of position:

Sinusoidal Positional Encoding

The original Transformer uses sinusoidal functions: PE(pos,2i)=sin(pos100002i/dmodel)PE_{(pos, 2i)} = \sin\left(\frac{pos}{10000^{2i/d_{model}}}\right) PE(pos,2i+1)=cos(pos100002i/dmodel)PE_{(pos, 2i+1)} = \cos\left(\frac{pos}{10000^{2i/d_{model}}}\right)
Positional Encoding Visualization

Learned Positional Embeddings

An alternative: learn position embeddings like word embeddings:

Attention with Masking

Causal (Autoregressive) Mask

For language models, we need to prevent attending to future positions:

Padding Mask

For variable-length sequences with padding:

Complete Attention-Based Seq2Seq


Exercises

Implement scaled dot-product attention without using any PyTorch attention functions:
  1. Implement the forward pass with proper scaling
  2. Add masking support (padding and causal)
  3. Verify gradients flow correctly
  4. Test on a simple sequence copying task
Using a pre-trained model (or train your own):
  1. Extract attention weights for various inputs
  2. Create visualizations showing what each head attends to
  3. Identify heads with interpretable patterns
  4. Compare attention patterns for different input types
Implement and compare:
  1. Dot-product attention
  2. Additive (Bahdanau) attention
  3. Multiplicative (Luong) attention
Train each on a translation task and compare:
  • Training speed
  • Final BLEU score
  • Attention patterns
Implement relative positional encoding:
  1. Instead of absolute positions, encode relative distances
  2. Modify attention scores to include position bias
  3. Compare with sinusoidal on long sequences
  4. Test extrapolation to longer sequences
Implement a more efficient attention mechanism:
  1. Implement local attention (attend only to nearby positions)
  2. Implement sparse attention patterns
  3. Compare memory usage and speed with full attention
  4. Evaluate impact on model quality

Training Pitfalls and Debugging Hints

Attention weights sum to 1 but that does not mean they are correct. A common mistake is interpreting attention weights as “explanation” for model behavior. Attention weights tell you where the model looked, not why it made its decision. Two models with identical outputs can have completely different attention patterns. Use attention visualizations for debugging intuition, not for mechanistic explanations.Uniform attention is a red flag. If your attention weights look roughly uniform (every position gets about 1/n attention), the model has not learned meaningful attention patterns. Common causes: (1) learning rate too low, (2) embedding quality is poor (the model cannot distinguish queries from keys), (3) the task does not actually require attention (try a simpler baseline).Attention memory scales quadratically with sequence length. For sequence length nn and hh heads, the attention weight matrix consumes O(n2h)O(n^2 \cdot h) memory. At n=4096n = 4096 with 12 heads in float32, that is about 750 MB per layer just for attention scores. If you run out of memory during training, sequence length is almost always the bottleneck — reduce it before reducing batch size.Mask shape mismatches: The most frustrating attention bug. PyTorch broadcasting rules mean a wrong mask shape often produces no error but silently computes the wrong thing. Always verify: padding masks should broadcast across heads and queries, causal masks should be square and lower-triangular, and the combination should use logical AND. Print mask.shape and scores.shape during debugging and verify they broadcast correctly.Multi-head attention head collapse: Sometimes all heads learn nearly identical attention patterns, wasting capacity. This happens with high dropout on attention weights or very small dkd_k (dimension per head). Monitor head diversity by computing the cosine similarity between attention patterns of different heads — if it is consistently above 0.9, you have collapse. Fix: reduce attention dropout, increase dkd_k, or add auxiliary losses that encourage head diversity.

Key Takeaways

The attention mechanism is the foundation of modern NLP. Understanding it deeply will help you grasp Transformers, BERT, GPT, and virtually all state-of-the-art language models.

What’s Next

Module 11: Transformers

Build the complete Transformer architecture — combine attention with feed-forward networks, layer normalization, and residual connections to create the model that revolutionized NLP.