Luong Attention › Worked Example: English-French Alignment

Michael BrenndoerferMay 18, 20256 min read
Language AI HandbookAll chapters
Part 12 of 67Sequence-to-Sequence
Chapter 88Luong Attention › Worked Example: English-French Alignment
Reading section 7 of 11 · Worked Example: English-French Alignment · 6 minSection 7 of 11 · 6 min

Book contents

Section 7 of 11 · 6 min read

Luong Attention › Worked Example: English-French AlignmentOne 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

The formulas we've discussed can feel abstract until you see them in action. Let's trace through a complete attention computation for a concrete translation example, following each step from raw hidden states to final attention weights.

Consider translating the English sentence "The cat sat" to French "Le chat assis". We'll focus on the moment when the decoder is about to generate the second French word "chat". At this point, the decoder needs to figure out which English word to focus on. Intuitively, it should attend to "cat" since that's the word being translated.

Setting Up the Problem

First, let's create simulated encoder hidden states for each English word. In a real model, these would come from running a bidirectional LSTM or transformer encoder over the input. Here, we'll craft vectors that capture the intuition: "cat" and the decoder state for "chat" should be similar, while "The" and "sat" should be less relevant.

In[15]:
Code
import numpy as np
import torch

np.random.seed(42)
torch.manual_seed(42)

# Create encoder representations that reflect semantic content:
# - "The": article with low semantic content (small magnitude)
# - "cat": noun with distinct pattern (will match decoder query)
# - "sat": verb with different pattern (won't match as well)
encoder_states = torch.tensor(
    [
        [0.1, 0.2, -0.1, 0.3],  # "The" - low magnitude, generic
        [0.8, -0.3, 0.9, 0.2],  # "cat" - strong noun pattern
        [0.2, 0.7, 0.1, -0.4],  # "sat" - different verb pattern
    ],
    dtype=torch.float32,
).unsqueeze(0)  # Add batch dimension for PyTorch

# Decoder hidden state when generating "chat"
# Designed to be similar to "cat" encoding
decoder_state = torch.tensor(
    [[0.7, -0.2, 0.8, 0.3]],  # Query vector looking for noun-like content
    dtype=torch.float32,
)
Out[16]:
Console
Encoder states shape: torch.Size([1, 3, 4])
Decoder state shape: torch.Size([1, 4])

The encoder states have shape (1, 3, 4): batch size 1, 3 source words, and 4-dimensional hidden states. The decoder state has shape (1, 4): a single 4-dimensional vector representing what the decoder is "looking for" when generating "chat".

Step 1: Computing Alignment Scores

Now we apply the dot product score function. For each encoder state, we compute its dot product with the decoder state. The dot product measures how much two vectors point in the same direction.

In[17]:
Code
# Compute dot product scores: decoder_state · each encoder_state
scores = torch.bmm(encoder_states, decoder_state.unsqueeze(2)).squeeze()

# Apply softmax to convert scores to probabilities
attention_weights = F.softmax(scores, dim=0)

# Compute context vector as weighted sum of encoder states
context = torch.bmm(
    attention_weights.unsqueeze(0).unsqueeze(0), encoder_states
).squeeze()

Step 2: Examining the Results

Let's see what scores each word received and how softmax converts them into attention weights:

Out[18]:
Console
Step-by-step attention computation:
----------------------------------------

Dot product scores (raw alignment):
  The: 0.0400
  cat: 1.4000
  sat: -0.0400

Attention weights (after softmax):
  The: 0.1718
  cat: 0.6695
  sat: 0.1586

Context vector: [0.585, -0.055, 0.601, 0.122]

Highest attention on: 'cat'

The results reveal exactly what we hoped to see. The decoder state for generating "chat" produces the highest alignment score with "cat" because their vectors point in similar directions. The softmax function then amplifies this difference: "cat" receives about 70% of the attention weight, while "The" and "sat" share the remaining 30%.

Notice how the context vector ends up being dominated by the "cat" representation. This is attention in action: the decoder has learned to extract the relevant information from the source sequence by focusing on the semantically corresponding word.

Out[19]:
Visualization
Bar chart showing attention weights with 'cat' receiving the highest weight around 0.7 highlighted in red.
Attention weights when generating 'chat' from 'The cat sat'. The model correctly focuses on 'cat' (shown in red), the source word that semantically corresponds to the French target. This alignment emerges from the similarity between the decoder hidden state and the 'cat' encoder representation, with 'cat' receiving roughly 70% of the attention weight.

The visualization below shows how the context vector is constructed as a weighted blend of the encoder states. Each dimension of the context vector is a weighted sum of that dimension across all encoder states, with the weights determined by attention.

Out[20]:
Visualization
Stacked bar chart showing weighted contributions from each encoder state to context vector dimensions.
Weighted contributions from each source word to the context vector dimensions. The 'cat' representation (red) dominates all four dimensions since it receives the highest attention weight (~70%). Diamond markers show the final context vector values, which closely match the stacked bar totals.
Grouped bar chart comparing encoder state values with the resulting context vector.
Comparison of the final context vector against each encoder state. The context closely resembles the 'cat' encoding (red bars) but is a smoothed blend across all three source words, shifted slightly toward 'The' and 'sat' by their small attention weights.