Skip to article frontmatterSkip to article content
Site not loading correctly?

This may be due to an incorrect BASE_URL configuration. See the MyST Documentation for reference.

Self-attention

In the previous chapter, position embedding let the GPT model know where each token is. Next, we need to make the model interact with the neighboring tokens on this basis.

An RNN model passes the information of earlier tokens to the current token through the hidden state. A GPT model, in contrast, processes all tokens in parallel, and no token knows anything about the others. Just as we told the model the position of a token with the position vector, we now need to tell the model explicitly how the current token is related to all the other tokens.

For example, how do humans read and understand? Take this sentence:

Ming bought apples, not bananas, because they are fresh.

When we reach “they”, we look back at what came before and put more of our attention on “apples” rather than “bananas”. This ability to look back and weigh the context according to the current content is what we want to simulate. It is called the attention mechanism.

Attention mechanism

The core idea of the attention mechanism is: when processing each token, first look back at all the tokens in the context, and assign them different weights according to how relevant they are:

  • tokens with high relevance get large weights and contribute more;

  • tokens with low relevance get small weights and contribute less.

Self-attention

Self-attention is a kind of attention mechanism: a token attends not to another sequence, but to the very sequence it belongs to. Every token plays two roles at the same time:

  • the attender: how do the other tokens affect me?

  • the attended: how do I affect the other tokens?

Attention weights

So how do we measure the relevance of two tokens? A simple and effective way is to compute the dot product of their word vectors:

scoreij=xi⋅xj\text{score}_{ij} = x_i \cdot x_j

The geometric meaning of the dot product is the agreement in direction of two vectors: the closer the directions, the larger the dot product, and the more relevant the two tokens are.

Computing the dot product for every pair of tokens gives an attention score matrix (attention scores) with the shape (context size, context size). The value in row ii and column jj is the relevance of the ii-th token to the jj-th token.

The values in the attention score matrix are not bounded, and using them directly would be unstable. We apply the Softmax activation function to turn each row into a probability distribution, which gives the attention weights: all the weights in each row sum to 1.

Self-attention weights: the weights of each token over all tokens in the context; each row passes through Softmax and sums to 1
Figure: self-attention weights

Dataset

Character-encoding dataset

Activation functions

Gaussian error linear unit (GELU)

Loss function

GPT cross-entropy loss function

Model

GPT embedding layer

GPT attention layer

We add a GPT attention layer to give the embedding vector of each token (word vector + position vector) the attention from the other tokens:

  • compute the attention score matrix: scores=X⋅XT\text{scores} = X \cdot X^T;

  • scale: multiply by 1/d1 / \sqrt{d} to prevent the values from getting too large, where dd is the embedding size embedding_size;

  • compute the attention weights: use the Softmax activation function to turn each row into a probability distribution;

  • weighted sum: multiply the attention weights by the embedding vectors to get a new attention vector that fuses the context.

Finally, we get the scaled dot-product attention:

Attention(X)=softmax(X⋅XTd)X\text{Attention}(X) = \text{softmax}\left(\frac{X \cdot X^T}{\sqrt{d}}\right) X

This is the core formula of the Transformer paper.

The code has one more step beyond the formula: the result of the weighted sum then passes through a linear layer self.output (the output projection) before it becomes the final output of the attention layer.

GPT feed-forward network layer

GPT Transformer block

Now we have the complete Transformer block: attention layer + feed-forward network layer.

  • Attention layer: lets tokens communicate with each other and fuse context information;

  • Feed-forward network layer: further refines the features of the fused attention vectors.

GPT basic modules with self-attention: the Transformer block consists of an attention layer and a feed-forward network layer
Figure: GPT basic modules with self-attention

GPT output layer

GPT model

GPT trainer

Hyperparameters

Learning rate

Batch size

Number of epochs

Context size

Embedding size

Number of Transformer blocks

Modeling

Training

Evaluation

prediction:	1742 steps, each (4, 32, 65)
loss:	2.872809682593143

Inference

ROMEO:::::M::MM:MMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMMM

In this chapter, we preliminarily implemented the most central mechanism of the GPT model: self-attention. Tokens can finally see each other, and every position fuses the relevant information of the whole context. The Transformer block has also been upgraded from a plain feed-forward network to the complete structure of “attention + feed-forward network”.

But the inference result is surprising: it fails completely. This is because the current self-attention has a fatal loophole: every token can see all positions, including the tokens after it. It is as if the model peeks at the answers during training, and gives itself away at inference.

In the next chapter, we will explore how to close this loophole.

Exercises

  1. What does the output projection of the GPT attention layer (the self.output linear layer) do? Try removing it and observe how the training results change.