Concepts / Self-Attention Mechanism

Self-Attention Mechanism

The SelfAttention_v1 class stores three trainable matrices, W_query, W_key, and W_value, each mapping the input dimension to the output dimension.

  • Programming
Interactive lab

Try it: Classes, Instances and Attributes

How a class creates instances with __init__ and self, why an attribute read checks the instance's __dict__ before the class, why assigning through an instance never changes the class, how a class-level list is shared by every instance, and why obj.method(x) is Class.method(obj, x).

How it works

  1. Dog(...) makes a new, empty instance and calls Dog.__init__(new_object, ...); self.name = ... stores into that object's __dict__.
  2. Reading obj.attr looks in obj.__dict__ first, then in the class.
  3. Assigning obj.attr = value always writes obj.__dict__, so it shadows a class attribute for that one object only.
  4. Mutating a class-level list (self.tricks.append) changes the one list every instance shares.
  5. obj.method is found on the class and bound to obj, so obj.method(x) runs Class.method(obj, x).

Default run (30 steps): Ready: class Dog and the statements you picked. Watch where each attribute is found and where each assignment writes. … Finished. Printed: ['sit'] / Wolf / Canis familiaris / Fido is 5.

Simplified: The lab's own small Python interpreter runs a fixed, hand-written script (you choose the variant and the values, never the code); nothing is executed as real Python. Every script was run in CPython 3.12 with the same inputs and the lab reproduces its output and error messages. Object numbers are illustrative, not real id() values.

Educational simulation

Loading the simulation…

Why a Word Needs Its Neighbours

Read a sentence and you constantly decide which other words matter for understanding a given word. A pronoun such as 'it' is meaningless until you connect it to something earlier in the text. A word near the end of a long passage may depend on a phrase introduced many words before it. Language is full of these links, and they do not always sit next to each other.

Transformers and large language models are built around a component called the self-attention mechanism, which is designed to handle exactly this problem. Its job is to let the model weigh the importance of different words or tokens in a sequence relative to each other. Because the weighing happens between the words of the input itself, the mechanism is described as self-attention.

This article follows one concrete implementation, a compact class called SelfAttention_v1, and traces it from its input to its output. Before you read the internals, you will practise forming a prediction about what the output should look like. The source notes that a self-attention class can look correct line by line and still produce a result you did not expect, and that the fastest way to catch this is to predict first and then check against what the code actually does.

Predicting the Output Shape First

The input is a matrix with one row per token, and each row is an embedding vector. Suppose the input has 6 tokens and each embedding has 3 values, so the input is 6 rows by 3 columns. The three weight matrices each map the input dimension d_in to the output dimension d_out. Use d_in equal to 3 and d_out equal to 2.

What do you think happens?

Before reading on: with 6 input tokens, d_in equal to 3, and d_out equal to 2, how many rows and columns does the output context matrix have?

  • 6 rows and 3 columns

  • 6 rows and 2 columns

  • 2 rows and 6 columns

  • 3 rows and 2 columns

Reveal answer
Answer:

6 rows and 2 columns, written as 6 by 2

The context vectors have one row per input token and d_out columns. The number of rows comes from the number of tokens, and the number of columns comes from the output dimension d_out, which is set by the weight matrices. The input dimension d_in does not appear in the final output shape.

The Class and Its Three Trainable Matrices

The class SelfAttention_v1 inherits from nn.Module. The source describes this base class as a fundamental building block of PyTorch models that supplies the functionality needed to create and manage model layers. Inheriting from it is what lets the class hold trainable parameters in a way PyTorch can track.

Inside the constructor, three trainable weight matrices are created: W_query, W_key, and W_value. Each one is wrapped in nn.Parameter and is sized so that it maps the input dimension d_in to the output dimension d_out. The three matrices start from random values, and the same input vectors are multiplied by each one to produce three different views of the data.

python
Notes on the code
  • The constructor creates the three trainable matrices; their shapes map d_in to d_out
  • nn.Parameter marks each matrix as a trainable parameter the model can learn
  • The forward method takes the input matrix x, one row per token
  • The scores come from comparing queries with keys
  • The context vectors are weights applied to the values

The sketch above is an illustrative reconstruction consistent with the description in the source, which explains each stage in prose rather than printing the full class. The line that divides by the square root of the key dimension is the scaling step that the source calls scaled softmax.

The constructor only sets up the starting values. The source explains that as the model is exposed to more data during training, it adjusts these trainable weights. Learning changes them later, which is why they are called trainable. This distinction matters when you debug: the matrices you see at construction time are not the ones the model ends up with.

Tracing the forward Method

The forward method is where the input actually flows through the mechanism. It takes the input matrix x, projects it into keys, queries, and values, computes a score for every pair of tokens, converts those scores into weights, and then uses the weights to combine the values. Read the method as a pipeline with five stages: receive the input, project it into queries, keys, and values, score every pair of tokens, turn the scores into weights, and combine the values using those weights.

Input xone row per tokenW_queryQueriesScoresone per pair of tokensAttention weightsscaled softmaxContext vectorsone row per tokenW_keyKeysW_valueValuesmultiplymultiplymultiplyprojectsprojectsprojectscompared withcompared withscale and softmaxweights applied toblended
In what order do the input and the three projections feed into forward(), and which stage produces the scores, the weights, and the context vectors?

The diagram traces the same flow the forward method performs, but as data flow instead of code. The input matrix X is multiplied by three weight matrices to produce queries, keys, and values. Queries and keys are combined into the attention weight matrix, and the weights are then applied to the values to produce the context vectors. Notice that the scores and weights sit between the projections and the final output. When something goes wrong, you can check the output of each stage rather than only the final result.

Weighing One Token Against Every Other

Take a single token, say token 2. Its query is compared against the key of every token in the sequence, including itself. Each comparison yields a score, and the scores become weights. The context vector for token 2 is then a weighted blend of the value vectors of all tokens, so tokens that score highly contribute more to it. Each token therefore gets its own context vector, shaped by its surroundings.

Query, token 2Key, token 1compared with queryContext vector, token2weighted blend of valuesKey, token 2compared with queryKey, token 3compared with queryKey, token 4compared with queryKey, token 5compared with queryKey, token 6compared with queryscorescorescorescorescorescoreweight times valueweight times valueweight times valueweight times valueweight times valueweight times value
How does one token's query get compared against every token's key, and how do the resulting weights blend the value vectors into a context vector for that token?

The example above shows the kind of judgement self-attention is meant to make: deciding which parts of the input bear on which other parts. It does not show how the model computes those judgements in detail. The source introduces the mechanism at this conceptual level and says nothing more specific about the arithmetic inside it.

Shape Propagation Through the Pipeline

Shape tracing is the most reliable way to find a bug before reading any numbers. The example below is an illustrative case written for this article, not taken from the source. It uses six input tokens, an input dimension of 3, and an output dimension of 2. Follow each intermediate tensor from the input to the final output.

Input x6 by 3W_query, W_key,W_valueeach 3 by 2Queries, keys, valueseach 6 by 2Scores6 by 6Attention weights6 by 6Context vectors6 by 2multiplied byproducesqueries times keys transposedscale and softmaxtimes values
How do the input shape and the shapes of W_query, W_key, and W_value determine the shape of each intermediate tensor and the final output?
Worked example

Predicting the Final Shape from the Inputs

Input x has 6 rows and 3 columns. Each weight matrix is 3 by 2. What are the shapes of the queries, keys, values, scores, weights, and context vectors?

  1. 1
    Projections

    Multiplying a 6 by 3 input by a 3 by 2 weight matrix gives a 6 by 2 result. The inner dimensions 3 and 3 match, and the outer dimensions give 6 by 2. Queries, keys, and values are all 6 by 2.

  2. 2
    Scores

    Queries multiplied by the transpose of keys is a 6 by 2 times a 2 by 6 product, giving 6 by 6. There is one score for every pair of tokens.

  3. 3
    Weights

    Applying softmax row by row to the scores keeps the shape, so the attention weights are also 6 by 6.

  4. 4
    Context vectors

    Weights (6 by 6) multiplied by values (6 by 2) gives 6 by 2. One row per token, with d_out columns.

Result

Queries, keys, values: 6 by 2. Scores and weights: 6 by 6. Context vectors: 6 by 2. The final output has one row per input token and d_out columns.

Checking the Output Row by Row

The source offers a simple way to verify the implementation. In the output matrix, the second row should match the context vector computed for the second input token in the single-token computation. Matching a row like this is a strong check, because it confirms that the batched matrix version and the single-token computation agree.

If the rows do not match, the mismatch tells you which part of the pipeline to examine. Because the forward method is a fixed sequence of matrix operations, you can check its output at each stage rather than only at the end. Compare the shapes first, then the projections, then the scores, then the weights, then the context vectors. The first stage that disagrees with your prediction is where the unexpected result begins.

MEDIUM

Your forward method returns a 6 by 6 matrix when you expected 6 by 2. Using the stage-by-stage check, which intermediate tensor would you inspect first, and why?

Hints
  • Compare the shapes of the queries, keys, and values first. Are they 6 by 2?
  • A 6 by 6 result is exactly the shape of the scores and the weights, not the context vectors.
  • If the context vectors are 6 by 6, check whether the final multiplication used the weights against the values, not against another matrix.

Mistakes Beginners Make with Self-Attention Shapes

  • Common mistake

    Expecting the output to have one column per input dimension

    What it looks like

    Assuming a 6 by 3 input produces a 6 by 3 context matrix because the input has 3 columns

    Why it fails

    The context vectors have d_out columns, which is set by the output dimension of the weight matrices, not by d_in.

    Do this instead

    Read the number of columns from d_out. Read the number of rows from the number of tokens.

  • Common mistake

    Treating the constructor's random matrices as the final learned weights

    Why it fails

    The constructor only sets up starting values. Training adjusts the trainable weights over time.

    Do this instead

    Check shapes at construction time, but do not expect the numbers to match a trained model.

  • Common mistake

    Reading the numbers in the source's figure as real attention weights

    Why it fails

    The source states those values were placed for visual consistency.

    Do this instead

    Use the figure to understand structure: weights come from queries and keys, and they act on values.

  • Common mistake

    Debugging only the final output instead of checking each stage

Why Self-Attention Captures Long-Range Dependencies

Self-attention is what allows a model to relate every position in an input to other positions, rather than reading each word in isolation. The source identifies two closely linked benefits. First, the mechanism enables the model to capture long-range dependencies, meaning relationships between words that sit far apart. Second, it captures contextual relationships within the input data, so that a token's role is shaped by its surroundings.

The reason this works is that a token's query is compared directly with the key of every other token in one step. A distant token is therefore no harder to reach than a neighbouring one. This is the contrast with a model that passes information only from one position to the next, where a distant clue would have to travel through every intermediate position.

The source connects these capabilities to output quality. By capturing these relationships, the mechanism enhances the model's ability to generate output that is coherent and contextually relevant. The reason self-attention matters is not only that it sees many words at once, but that it uses those words to judge what each one means in its setting.

How Encoder and Decoder Divide the Translation Work

The self-attention mechanism appears within a larger structure. A transformer is a deep learning model architecture for language translation. In the simplified depiction the source gives, it is made of two parts: an encoder and a decoder. In the original transformer architecture, the encoder processes the complete input text and produces an embedding representation, and the decoder uses that representation to generate output one word at a time.

Consider one translation. The input text is the sentence 'This is an example', and the partially translated sentence is 'Das ist ein'. The final stage is where the decoder has to generate only the last word, 'Beispiel', to complete the translation. The encoder has already read the whole input, so the decoder's job at this point is to produce the remaining output word using the representation it was handed.

Keeping these jobs separate makes it easier to see where the attention-based weighing of words does its work. The encoder is where the input is read as a whole, and the decoder depends on the representation that results. The source's introductory treatment places self-attention within this two-part structure without describing the internal arithmetic of either part in detail.

Where the Full Explanation Is Deferred

When you reach the detailed treatment, keep the structure from this article in mind. The shapes you predicted, the five stages of the forward method, and the row-by-row check will still apply. The later material supplies the mathematics behind each stage.

Key Takeaways

  • Self-attention lets a model weigh the importance of different tokens in a sequence relative to each other, which helps capture long-range dependencies and context.
  • SelfAttention_v1 inherits from nn.Module and holds three trainable matrices, W_query, W_key, and W_value, each mapping d_in to d_out.
  • The forward method projects the input into queries, keys, and values, scores token pairs, converts scores into weights, and combines values into context vectors.
  • Predicting shapes first makes the output checkable: with 6 tokens and d_out of 2, the context vectors are 6 by 2, and the scores and weights are 6 by 6.
  • Checking the output row by row and stage by stage locates where an unexpected result first diverges. In the transformer, the encoder reads the input and the decoder generates the output one word at a time.

Related concepts

More concepts starting with S