Bahdanau Attention › The Attention Mechanism: From Intuition to Formulas

Michael BrenndoerferUpdated May 22, 202523 min read
Language AI HandbookAll chapters
Part 12 of 67Sequence-to-Sequence
Chapter 87Bahdanau Attention › The Attention Mechanism: From Intuition to Formulas
Reading section 3 of 11 · The Attention Mechanism: From Intuition to Formulas · 23 minSection 3 of 11 · 23 min

Book contents

Section 3 of 11 · 23 min read

Bahdanau Attention › The Attention Mechanism: From Intuition to FormulasOne section · Sections in this chapter3 / 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

With the alignment problem clearly defined, we can now develop the mathematical machinery that Bahdanau attention uses to solve it. Our journey will take us through three interconnected concepts: computing relevance scores, converting those scores to probabilities, and aggregating information based on those probabilities. Each piece builds naturally on the previous one, culminating in a mechanism that allows the decoder to "look back" at exactly the right parts of the input at each generation step.

The Challenge of Measuring Relevance

Attention addresses a simple question: when the decoder is about to generate output token ii, how relevant is each encoder position jj to that decision? If we could answer this question with a single number for each encoder position, we'd have a way to rank and weight the encoder states.

But what should this "relevance score" capture? Consider translating "The cat sat on the mat" to French. When generating "chat" (cat), the decoder needs to know:

  • What the decoder is currently looking for (encoded in its hidden state si−1s_{i-1})
  • What information each encoder position offers (encoded in hidden states h1,h2,…,hTxh_1, h_2, \ldots, h_{T_x})

The relevance of position jj depends on both of these: what hjh_j contains and whether that content matches what the decoder currently needs. This suggests we need a function that takes both the decoder state and an encoder state as inputs and produces a scalar score.

The Additive Score Function

Bahdanau and colleagues designed a solution called the additive (or concatenative) alignment model. Rather than directly comparing the decoder and encoder states, which might have different dimensions and represent different types of information, they project both into a shared "alignment space" where comparison becomes meaningful.

The alignment score between decoder position ii and encoder position jj is computed as:

eij=va⊤tanh⁡(Wasi−1+Uahj)e_{ij} = v_a^\top \tanh(W_a s_{i-1} + U_a h_j)

where:

  • eije_{ij}: the alignment score, a scalar indicating how relevant encoder position jj is for generating output ii
  • si−1∈Rdss_{i-1} \in \mathbb{R}^{d_s}: the decoder hidden state at the previous timestep, encoding what the decoder "knows" and "needs"
  • hj∈Rdhh_j \in \mathbb{R}^{d_h}: the encoder hidden state at position jj, encoding information about input token jj and its context
  • Wa∈Rda×dsW_a \in \mathbb{R}^{d_a \times d_s}: a learnable weight matrix that projects the decoder state into the alignment space
  • Ua∈Rda×dhU_a \in \mathbb{R}^{d_a \times d_h}: a learnable weight matrix that projects encoder states into the same alignment space
  • va∈Rdav_a \in \mathbb{R}^{d_a}: a learnable vector that reduces the combined representation to a scalar
  • dad_a: the dimension of the alignment space (a hyperparameter, typically matching the hidden dimensions)

This formula might look complex at first glance, but it follows a clear logic. Let's trace through it step by step to understand why each component is necessary:

Step 1: Project into alignment space. The decoder state si−1s_{i-1} and encoder state hjh_j live in potentially different vector spaces with different dimensions. Before comparing them, we need to transform them into a common representation. The matrices WaW_a and UaU_a learn these transformations during training:

  • Wasi−1W_a s_{i-1} produces a dad_a-dimensional vector representing "what the decoder is looking for"
  • UahjU_a h_j produces a dad_a-dimensional vector representing "what encoder position jj offers"

Step 2: Combine additively. With both vectors in the same space, we add them element-wise: Wasi−1+UahjW_a s_{i-1} + U_a h_j. This additive combination allows the model to detect when the decoder's query and the encoder's content are compatible. If certain dimensions align well (both positive or both negative), they reinforce each other; if they conflict, they cancel out.

Step 3: Apply nonlinearity. The tanh⁡\tanh function serves two purposes. First, it bounds the values to [−1,1][-1, 1], preventing any single dimension from dominating. Second, it introduces nonlinearity, enabling the model to learn complex, non-linear relationships between decoder queries and encoder contents. Without this nonlinearity, the entire alignment model would collapse to a simple linear function.

Out[5]:
Visualization
Plot of the tanh function showing bounds at plus and minus one with shaded saturation regions.
The tanh function compresses extreme values while preserving values near zero. Saturation regions (shaded) show where inputs are bounded to ±1.
Histogram comparing score distributions before and after tanh transformation.
Distribution of combined scores before and after tanh transformation. The tanh function prevents extreme values from dominating the alignment scores.

Step 4: Reduce to scalar. Finally, the dot product with vav_a compresses the dad_a-dimensional result into a single scalar score. The vector vav_a learns which dimensions of the alignment space are most important for determining relevance. Some dimensions might capture semantic similarity, others syntactic compatibility; vav_a learns to weight these appropriately.

Out[6]:
Visualization
Flow diagram showing decoder state and encoder state being projected, added, passed through tanh, and multiplied by v to produce score.
The additive score function in Bahdanau attention. The decoder state and each encoder state are projected into a shared alignment space, combined additively, passed through tanh, and reduced to a scalar score.

Why "additive" rather than some other approach? Additive combination with separate projection matrices gives the model maximum flexibility. The decoder and encoder might have different hidden dimensions, and even if they're the same size, they encode different types of information. By learning separate projections WaW_a and UaU_a, the model can transform each representation into whatever form makes comparison most effective. Bahdanau and colleagues found this approach worked well in practice, and it became the foundation for subsequent attention mechanisms.

From Scores to Probabilities: The Softmax Transformation

We now have a way to compute alignment scores eije_{ij} for each encoder position. But these raw scores can be any real number: positive, negative, or zero. To use them for weighting encoder states, we need to transform them into something more interpretable: a probability distribution over encoder positions.

This is where the softmax function enters the picture. Softmax takes a vector of arbitrary real numbers and converts it into a valid probability distribution where all values are positive and sum to 1:

αij=exp⁡(eij)∑k=1Txexp⁡(eik)\alpha_{ij} = \frac{\exp(e_{ij})}{\sum_{k=1}^{T_x} \exp(e_{ik})}

where:

  • αij\alpha_{ij}: the attention weight for encoder position jj when generating output ii
  • eije_{ij}: the raw alignment score from our scoring function
  • exp⁡(⋅)\exp(\cdot): the exponential function (exe^x)
  • TxT_x: the length of the source sequence
  • ∑k=1Txexp⁡(eik)\sum_{k=1}^{T_x} \exp(e_{ik}): the normalizing constant that ensures weights sum to 1

The exponential function is the key to softmax's behavior. It has two essential properties that make it ideal for attention:

  1. Positivity: exp⁡(x)>0\exp(x) > 0 for all real xx, guaranteeing non-negative weights regardless of the input scores
  2. Monotonicity with amplification: larger scores produce exponentially larger values, which amplifies differences between scores

This second property is particularly important. Consider two scores: ei1=1.2e_{i1} = 1.2 and ei2=3.5e_{i2} = 3.5. The difference looks modest, but after exponentiation, exp⁡(3.5)≈33\exp(3.5) \approx 33 while exp⁡(1.2)≈3.3\exp(1.2) \approx 3.3, a 10x ratio. Softmax creates a "winner-take-most" dynamic where the highest-scoring positions dominate, while still allowing lower-scoring positions to contribute.

The attention weight αij\alpha_{ij} has a clear interpretation: it represents the probability that encoder position jj contains the information most relevant for generating output token ii. When we compute attention, we're asking: "Given what the decoder currently needs, where in the input should it look?"

Out[7]:
Visualization
Bar chart of raw alignment scores for seven encoder positions, with position 4 highlighted as the highest scorer.
Raw alignment scores for seven encoder positions. Position 4 has the highest score (2.8), but the differences appear modest.
Bar chart of attention weights after softmax normalization, showing position 4 receiving disproportionately more weight.
After softmax normalization, position 4 receives disproportionately more weight, which demonstrates the 'winner-take-most' amplification effect.

The visualization above shows this amplification in action. Position 4 has a raw score of 2.8, only about 2× higher than position 1's score of 0.8. But after softmax, position 4 receives about 4× the attention weight of position 1. This amplification helps the model make decisive choices about where to focus.

Beyond the mathematical properties, softmax has two important advantages for learning:

  1. Differentiability: Gradients flow smoothly through softmax, enabling end-to-end training with backpropagation.
  2. Soft selection: Unlike "hard" attention (which would pick exactly one position), soft attention maintains gradients to all positions, making optimization much easier.

The "softness" of attention can be controlled by scaling the scores before applying softmax. Dividing scores by a temperature parameter τ\tau changes how sharply the attention focuses:

Out[8]:
Visualization
Bar chart showing attention weights at low temperature tau=0.3, with nearly all weight on one position.
Low temperature (τ=0.3) produces nearly hard attention, with 97% weight on the highest-scoring position.
Bar chart showing attention weights at standard temperature tau=1.0, with moderate focus.
Low temperature (τ=0.3) produces nearly hard attention, with 97% weight on the highest-scoring position.
Bar chart showing attention weights at high temperature tau=3.0, with nearly uniform distribution.
Low temperature (τ=0.3) produces nearly hard attention, with 97% weight on the highest-scoring position.

The entropy values in the figure quantify the "spread" of attention: lower entropy means more focused attention, higher entropy means more distributed. Standard Bahdanau attention uses τ=1\tau = 1, which provides a good balance between focusing on relevant positions and maintaining gradient flow to all positions during training.

The "sharpness" of the attention distribution depends on the magnitude of score differences. When scores are similar, attention spreads across many positions; when one score is much higher, attention concentrates sharply:

Out[9]:
Visualization
Bar chart showing spread attention weights across seven encoder positions with similar scores.
Spread attention when scores are similar (low variance). Weights distribute relatively evenly across positions (H = 1.91).
Bar chart showing focused attention with most weight on position 4.
Focused attention when one score dominates (high variance). Position 4 captures most of the attention (H = 0.98).

The entropy values quantify this difference: higher entropy indicates more spread-out attention, while lower entropy indicates more concentrated attention. A well-trained model learns to produce focused attention when one input position is clearly relevant (e.g., translating a content word) and spread attention when multiple positions contribute (e.g., translating a phrase that spans multiple source words).

Aggregating Information: The Context Vector

We've now computed attention weights αij\alpha_{ij} that tell us how much the decoder should attend to each encoder position. The final step is to use these weights to create a single vector that summarizes the relevant information from the entire input sequence. This is the context vector.

The context vector for decoder position ii is simply a weighted sum of the encoder hidden states:

ci=∑j=1Txαijhjc_i = \sum_{j=1}^{T_x} \alpha_{ij} h_j

where:

  • ci∈Rdhc_i \in \mathbb{R}^{d_h}: the context vector, a dhd_h-dimensional summary of the relevant input information
  • αij\alpha_{ij}: the attention weight for encoder position jj (how much to attend to that position)
  • hj∈Rdhh_j \in \mathbb{R}^{d_h}: the encoder hidden state at position jj
  • TxT_x: the length of the source sequence

This formula is simple, but its implications are significant. Because the attention weights sum to 1, the context vector is a convex combination of the encoder states. It lies somewhere "between" them in the vector space, closer to the states with higher weights.

Consider what happens in different scenarios:

  • Focused attention: If αi2=0.95\alpha_{i2} = 0.95 and all other weights are near zero, then ci≈h2c_i \approx h_2. The context vector copies the encoder state at position 2.
  • Distributed attention: If weights are spread across multiple positions, the context vector blends information from all of them. This is useful when the decoder needs information from multiple parts of the input.
  • Uniform attention: If all weights are equal (αij=1/Tx\alpha_{ij} = 1/T_x), the context vector is the simple average of all encoder states, similar to a mean-pooling operation.
Out[10]:
Visualization
Scatter plot showing encoder states in 2D space with context vector star positioned near h3 due to focused attention.
Focused attention places the context vector (star) near $h_3$ which receives 85% of the attention weight.
Scatter plot showing encoder states in 2D space with context vector star positioned between multiple states due to distributed attention.
Distributed attention places the context vector between multiple encoder states, blending information from all positions.

This geometric interpretation helps build intuition: the context vector "moves" through the encoder state space based on attention weights, getting pulled toward whichever states receive more attention. The model learns to position the context vector where it captures the most relevant information for the current generation step.

The key insight is that each decoder step gets its own context vector cic_i, computed fresh based on the current decoder state si−1s_{i-1}. This is the main improvement over standard encoder-decoder models: instead of forcing all information through a single fixed-size bottleneck, we dynamically select and aggregate the relevant parts of the input at each generation step.

Out[11]:
Visualization
Diagram showing encoder states being multiplied by attention weights and summed to produce context vector.
The context vector is computed as a weighted sum of encoder hidden states: $c_i = \sum_{j} \alpha_{ij} h_j$. Positions with higher attention weights contribute more to the final context. This dynamic weighting allows the decoder to focus on relevant parts of the input at each step.

Putting It All Together: The Complete Attention Mechanism

We've now developed all three components of Bahdanau attention:

  1. Scoring: eij=va⊤tanh⁡(Wasi−1+Uahj)e_{ij} = v_a^\top \tanh(W_a s_{i-1} + U_a h_j) measures relevance
  2. Normalization: αij=softmax(eij)\alpha_{ij} = \text{softmax}(e_{ij}) converts scores to probabilities
  3. Aggregation: ci=∑jαijhjc_i = \sum_j \alpha_{ij} h_j creates a weighted summary

But how does this attention mechanism integrate with the decoder RNN? The context vector cic_i contains a summary of the relevant input information, but the decoder also needs to know what it has generated so far and maintain its own internal state.

In Bahdanau's formulation, these three sources of information are combined by feeding them into the decoder RNN:

si=f(si−1,yi−1,ci)s_i = f(s_{i-1}, y_{i-1}, c_i)

where:

  • si∈Rdss_i \in \mathbb{R}^{d_s}: the new decoder hidden state after processing step ii
  • si−1∈Rdss_{i-1} \in \mathbb{R}^{d_s}: the previous decoder hidden state (the decoder's "memory")
  • yi−1∈Rdey_{i-1} \in \mathbb{R}^{d_e}: the embedding of the previous output token
  • ci∈Rdhc_i \in \mathbb{R}^{d_h}: the context vector from attention
  • ff: a recurrent cell function (typically GRU or LSTM)

In practice, yi−1y_{i-1} and cic_i are concatenated into a single vector of dimension de+dhd_e + d_h before being fed to the RNN. This combines information about the previous prediction with the attention-weighted summary of the input.

The complete decoding process at step ii follows this sequence:

  1. Compute alignment scores: For each encoder position jj, calculate eij=va⊤tanh⁡(Wasi−1+Uahj)e_{ij} = v_a^\top \tanh(W_a s_{i-1} + U_a h_j)
  2. Normalize to attention weights: Apply softmax to get αij\alpha_{ij}
  3. Compute context vector: Calculate ci=∑jαijhjc_i = \sum_j \alpha_{ij} h_j
  4. Update decoder state: Compute si=f(si−1,yi−1,ci)s_i = f(s_{i-1}, y_{i-1}, c_i)
  5. Generate output: Predict the next token using sis_i (and often cic_i as well)

One subtle but important detail: attention is computed using the previous decoder state si−1s_{i-1}, not the current state sis_i. This makes sense because we need to know what the decoder is looking for before we can compute the context, and we need the context before we can update the decoder state.

Out[12]:
Visualization
Flow diagram showing attention computation integrated into decoder RNN at each timestep.
The complete attention mechanism in the decoder. At each step, the decoder uses its previous state to compute attention over encoder states, produces a context vector, and combines this with the previous output to generate the next hidden state and output prediction.