Query, Key, and Value Projections
Weight parameters are learned coefficients optimized during training, while attention weights are dynamic, context-specific values that determine how much a context vector depends on each part of the input.
Why the Word Weight Causes Confusion
Many learners first meet the word 'weight' in a neural network course, where it means a number that training adjusts until the model works. That meaning is reasonable, and it is also the source of a common confusion once attention enters the picture. The word appears in two places that play very different roles. One is the set of weight matrices that a self-attention layer learns. The other is the attention weights that the mechanism computes while it runs. This article separates the two meanings before explaining how attention scores and weights are produced, because the rest of the computation depends on knowing which values are fixed by training and which are produced fresh for each query.
What do you think happens?
When the same self-attention layer processes two different queries, does the query weight matrix W_q change between the two computations?
Reveal answer
No, it stays the same once training has finished.
The weight matrices are learned coefficients set during training. What changes from query to query are the attention weights, which are computed during the forward pass for each context.
Weight Parameters Versus Attention Weights
In the weight matrices of self-attention, 'weight' is short for 'weight parameters'. These are values of a neural network that are optimized during training. They are the fundamental, learned coefficients that define the network's connections, and once training has set them, they describe how the network connects its inputs to its outputs.
Attention weights are a separate quantity. They determine the extent to which a context vector depends on the different parts of the input. In other words, they express how strongly the network focuses on each input element when it builds the context vector for one query. Because they are computed fresh for each query, they are dynamic and context-specific rather than fixed coefficients.
The clean way to hold on to the distinction is to ask when each value is determined. Weight parameters are settled by training and then used. Attention weights are produced during a forward computation, so the same weight matrix can yield different attention weights for different queries.
| Property | Weight parameters | Attention weights |
|---|---|---|
| When they are determined | Set during training | Computed during each forward pass |
| Do they change between queries | No, they are fixed after training | Yes, they are recomputed for every query |
| What they describe | Connections between inputs and outputs in the network | How strongly a context vector depends on each input element |
| Where they come from | Optimization during training | Scores produced from query and key vectors, then scaled and normalized |
Weight parameters and attention weights answer different questions about the same layer.
Projecting Inputs into Queries, Keys, and Values
Suppose the goal is only to compute a single context vector for one input token. It is still necessary to have key and value vectors for every input element, because all of the keys take part in computing the attention weights with respect to the query. Keys and values for the full set of inputs can be obtained together by matrix multiplication with the key and value weight matrices.
This projection is what maps each input token from its original embedding space into the space of queries, keys, and values. The source example projects six input tokens from a three-dimensional space onto a two-dimensional embedding space, so each token ends up with a two-dimensional key and a two-dimensional value. The same input representation therefore yields three different vectors, and each one is produced by its own learned weight matrix.
Computing a Raw Attention Score
The second step is to compute attention scores. An attention score is computed as a dot product between a query vector and a key vector. This is the same kind of dot-product computation used in the simplified self-attention mechanism, with one new aspect: the query and the key are not the raw input elements. They are obtained by transforming the inputs through their respective weight matrices. The result is one unnormalized number that measures how well the query matches that key.
Indexing matters when you locate a score. The source computes the score for the second input token first. The query comes from that second token and is paired with the key at index 1. Python starts indexing at 0, so the second key is keys[1], not keys[2].
Rather than repeating that dot product for every key, the same results can be obtained for all keys at once by multiplying the query by the transposed key matrix. The second entry of the resulting row matches the single score computed earlier, which is a useful quick check when you write this code yourself.
Turning Scores into Attention Weights
Attention scores are not yet attention weights. The next step converts the scores by scaling them and then applying the softmax function. The scaling divides each score by the square root of the embedding dimension of the keys. Taking the square root is mathematically the same as raising to the power 0.5.
In this formula, $\omega_{i}$ is an unnormalized attention score, $d_{k}$ is the embedding dimension of the keys, and $w_{i}$ is the resulting attention weight for that key. The source code performs the same steps: it reads the key dimension from the shape of the keys, divides the scores by its square root, and applies softmax along the last dimension.
Softmax is what converts the scaled scores into the weights. Its output values are positive and add up to one across the dimension it is applied to. The attention weights for one query therefore form a distribution over the input tokens: larger weights mean the context vector leans more heavily on those tokens.
Scores to weights for one query
The query is [1, 0]. The three keys are [1, 0], [0, 1], and [1, 1]. Each key has dimension d_k = 2. Compute the raw scores, scale them, and apply softmax across the three keys.
- 1Compute raw scores
Dot products: [1, 0] dot [1, 0] = 1, [1, 0] dot [0, 1] = 0, [1, 0] dot [1, 1] = 1.
- 2Scale by the square root of d_k
The square root of 2 is about 1.414, so the scaled scores are 1 / 1.414 = 0.707, 0 / 1.414 = 0, and 0.707.
- 3Exponentiate
e raised to 0.707 is about 2.028, and e raised to 0 is 1. The sum is 2.028 + 1 + 2.028 = 5.056.
- 4Normalize with softmax
Divide each value by 5.056: 2.028 / 5.056 is about 0.401, 1 / 5.056 is about 0.198, and 2.028 / 5.056 is about 0.401.
The attention weights are approximately 0.401, 0.198, and 0.401. They are positive and sum to 1.0, and the first and third keys receive the most weight.
Tracing a Wrong Result Step by Step
When a computed score or weight does not match what you expected, the source gives a fixed order for locating the problem: check the query source, the key index, the scaling step, and the softmax axis, in that order. Following the order matters because each check depends on the one before it. A wrong query source makes every later score wrong, while a softmax axis error only appears after the scores are already correct.
Common mistake Pairing the query with the wrong key index
What it looks likeReading the second key as keys[2] when the source pairs the second token's query with keys[1].
Why it failsPython indexes from 0, so the second element sits at index 1.
Do this insteadConfirm the index with the position counted from zero before comparing the score.
Common mistake Using raw input vectors instead of projected queries and keys
What it looks likeTaking the dot product of two input token embeddings directly.
Why it failsScores are computed from queries and keys obtained by transforming inputs through their weight matrices.
Do this insteadCheck that the query and key come from W_q and W_k before the dot product is taken.
Common mistake Skipping the scaling step
What it looks likeApplying softmax directly to the raw score 1 and getting a weight that is too sharp.
Why it failsThe source scales the scores by the square root of the key embedding dimension before softmax.
Do this insteadDivide each raw score by the square root of d_k first, reading d_k from the shape of the keys.
Common mistake Normalizing across the wrong dimension
What it looks likeApplying softmax down a column when the weights for one query should sum to one across the keys.
Why it failsThe source applies softmax along the last dimension, which produces one distribution per query.
Do this insteadConfirm the softmax axis is the key dimension, the last one, so each query's weights sum to 1.0.
Common mistake Treating attention weights as fixed parameters that training should update
Keep a small hand-computed example, such as the two-dimensional query and key worked above, and run your code on it. If the scores and weights match the hand values, the pipeline is probably correct for real inputs too.
Practice: Tracing a Score Through the Pipeline
A query is [0, 1] and the key at index 2 is [0, 1] with key dimension d_k = 4. Compute the raw score, the scaled score, and state which of the four checks you would perform first if your code returned a weight of 0.5 for a different key.
Hints
- The raw score is the dot product of the query and the key.
- The square root of 4 is 2.
- Start the check with the query source, then the key index, then scaling, then the softmax axis.
Key Takeaways
- Weight parameters are learned during training and then fixed, while attention weights are recomputed for each query and context.
- An attention score is a raw, unnormalized dot product between a query vector and a key vector, and Python pairs the second token with keys[1].
- Attention weights come from dividing each score by the square root of the key dimension and then applying softmax along the last dimension.
- Softmax outputs are positive and sum to one, so the weights for one query form a distribution over input tokens.
- To locate a wrong value, check the query source, key index, scaling, and softmax axis in that order.