Attention Mechanism Explained: The Math Behind Q, K, and V

· llmaimachine-learningtransformers

The Library Analogy

Imagine you walk into a massive library looking for a book about black holes. You walk up to the front desk and describe what you want: “I need something about the physics of black holes.” The librarian listens to your description, compares it against every book’s title and summary in the catalog, and then hands you the three most relevant books.

That is exactly how the attention mechanism works in a Transformer:

  • You are a word in a sentence. Your description of what you want is your Query (Q).
  • The catalog entries for every book are the Keys (K). Each book advertises what it contains.
  • The actual books the librarian hands you are the Values (V). These are the real information you receive.

The librarian compares your Query against every Key, scores the match, and then gives you a weighted blend of the most relevant Values. The stronger the match between your Query and a Key, the more of that book’s Value you receive.

This one mechanism — repeated billions of times inside models like GPT, Claude, and Gemini — is what lets them understand context, resolve pronouns, and reason about meaning.

The Attention Formula

The core formula for Scaled Dot-Product Attention is:

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V

Let us decode each piece:

SymbolMeaningLibrary Analogy
QQQuery matrixYour search description
KKKey matrixEvery book’s catalog entry
VVValue matrixThe actual book contents
KTK^TTranspose of KKRearranging the catalog for comparison
dkd_kDimension of KK vectorsLength of each catalog entry
dk\sqrt{d_k}Square root of dkd_kA scaling factor to keep scores stable
softmaxNormalization functionConverting match scores into percentages

Do not worry if this looks abstract. We will walk through every single operation with real numbers. By the end of this post, each symbol in that formula will feel intuitive.

The key idea: we compare what each word is looking for (QQ) with what every other word offers (KK), then collect the actual information (VV) from the most relevant words.

From Words to Numbers

Neural networks do not understand text. They understand numbers. So before attention can do anything, we need to convert words into vectors — lists of numbers that capture meaning.

Let us use a simple sentence: “I love AI”

In a real model, each word becomes a vector of 512 or 1024 numbers. For our walkthrough, we will use tiny 4-dimensional vectors so we can do the math by hand:

"I"[1.00.01.00.0]"love"[0.01.00.01.0]"AI"[1.01.00.00.0]\text{"I"} \rightarrow \begin{bmatrix} 1.0 & 0.0 & 1.0 & 0.0 \end{bmatrix} \quad \text{"love"} \rightarrow \begin{bmatrix} 0.0 & 1.0 & 0.0 & 1.0 \end{bmatrix} \quad \text{"AI"} \rightarrow \begin{bmatrix} 1.0 & 1.0 & 0.0 & 0.0 \end{bmatrix}

Think of each dimension as a different “feature detector.” Dimension 1 might respond to pronouns. Dimension 2 might respond to verbs. Dimension 3 might respond to technical terms. The exact interpretation does not matter — the model learns these representations during training.

We stack these three vectors into an input matrix XX of shape 3×43 \times 4 (3 words, 4 dimensions each):

X=[1.00.01.00.00.01.00.01.01.01.00.00.0]"I""love""AI"X = \begin{bmatrix} 1.0 & 0.0 & 1.0 & 0.0 \\ 0.0 & 1.0 & 0.0 & 1.0 \\ 1.0 & 1.0 & 0.0 & 0.0 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

Each row is a word. Each column is a dimension. This matrix XX is our starting point.

Click a word to explore its embedding vector

Click through the words above to see how text becomes vectors. In a real model, these embeddings are learned from massive datasets, not set by hand. But the principle is the same: every word becomes a row of numbers.

Creating Q, K, and V

A single set of embeddings is not enough. The attention mechanism needs three different “views” of the input — one for searching, one for being searched, and one for delivering content.

We create these three views by multiplying XX with three separate weight matrices:

Q=XWQK=XWKV=XWVQ = XW_Q \qquad K = XW_K \qquad V = XW_V

Think of each weight matrix as a lens that projects the input into a different space. WQW_Q extracts “what am I looking for?” information. WKW_K extracts “what do I contain?” information. WVW_V extracts “what information should I share?” information.

In our example, we want QQ, KK, and VV vectors of size 3 (so dk=3d_k = 3). Each weight matrix has shape 4×34 \times 3 (mapping from 4 input dimensions to 3 output dimensions). Here are our weight matrices:

WQ=[101010100011]WK=[010101001110]WV=[100010001110]W_Q = \begin{bmatrix} 1 & 0 & 1 \\ 0 & 1 & 0 \\ 1 & 0 & 0 \\ 0 & 1 & 1 \end{bmatrix} \quad W_K = \begin{bmatrix} 0 & 1 & 0 \\ 1 & 0 & 1 \\ 0 & 0 & 1 \\ 1 & 1 & 0 \end{bmatrix} \quad W_V = \begin{bmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ 1 & 1 & 0 \end{bmatrix}

Let us compute Q=XWQQ = XW_Q. For the first row (“I”):

[11+00+11+00,10+01+10+01,11+00+10+01]=[201]\begin{bmatrix} 1 \cdot 1 + 0 \cdot 0 + 1 \cdot 1 + 0 \cdot 0, & 1 \cdot 0 + 0 \cdot 1 + 1 \cdot 0 + 0 \cdot 1, & 1 \cdot 1 + 0 \cdot 0 + 1 \cdot 0 + 0 \cdot 1 \end{bmatrix} = \begin{bmatrix} 2 & 0 & 1 \end{bmatrix}

Doing this for all three words:

Q=[201021111]"I""love""AI"Q = \begin{bmatrix} 2 & 0 & 1 \\ 0 & 2 & 1 \\ 1 & 1 & 1 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

Similarly, K=XWKK = XW_K:

K=[011211111]"I""love""AI"K = \begin{bmatrix} 0 & 1 & 1 \\ 2 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

And V=XWVV = XW_V:

V=[101120110]"I""love""AI"V = \begin{bmatrix} 1 & 0 & 1 \\ 1 & 2 & 0 \\ 1 & 1 & 0 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

In a real Transformer, these weight matrices are not set by hand. They are learned during training — the model discovers the best projections automatically by seeing billions of examples.

Input Embedding Matrix
Input X
I
1
0
1
0
love
0
1
0
1
AI
1
1
0
0
Each row is a token embedding. We project these into Query, Key, and Value spaces using learned weight matrices.

Step through the projection above to see how each word’s embedding gets multiplied by the weight matrices to produce Q, K, and V. Notice how the same input produces three different representations depending on which lens we look through.

Computing Attention Scores

Now comes the heart of attention: comparing every word’s Query against every word’s Key. We do this by computing QKTQK^T (the Query matrix times the transpose of the Key matrix).

First, let us transpose KK. Transposing means swapping rows and columns:

KT=[021111111]K^T = \begin{bmatrix} 0 & 2 & 1 \\ 1 & 1 & 1 \\ 1 & 1 & 1 \end{bmatrix}
K
0
1
2
I
love
AI
0
1
1
2
1
1
1
1
1

Rows become columns. The element at position (i,j) moves to (j,i).

Click “Transpose” above to watch each element physically move to its new position. The diagonal elements (0, 1, 1) stay put while the off-diagonal pairs swap places.

Now we multiply QQ (3×33 \times 3) by KTK^T (3×33 \times 3) to get a 3×33 \times 3 score matrix. Each cell tells us how much one word should “pay attention” to another.

For “I” attending to “love”: dot product of QQ‘s first row with KTK^T‘s second column:

22+01+11=52 \cdot 2 + 0 \cdot 1 + 1 \cdot 1 = 5
Dot Product
Q row "I" dot K^T column "love"
Q: 'I'
K^T: 'love'
2
0
1
2
1
1
Click Multiply to see the dot product step by step

Watch the multiplication above: the row slides across the column, element pairs light up one by one, and the running total accumulates to the final score of 5.

The word “I” scores “love” a 5 — the highest score in the entire matrix. This means “I” finds “love” the most relevant word in the sentence. That makes linguistic sense: “I” is a pronoun that needs context, and “love” tells us what “I” is doing.

Computing the full score matrix:

Scores=QKT=[153333243]"I""love""AI"\text{Scores} = QK^T = \begin{bmatrix} 1 & 5 & 3 \\ 3 & 3 & 3 \\ 2 & 4 & 3 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

Key observations:

  • “I” strongly attends to “love” (score 5). The pronoun needs the verb for context.
  • “love” attends equally to all words (score 3 each). As the central verb, it connects everything.
  • “AI” attends most to “love” (score 4), then itself (3), then “I” (2).
Attention Scores: Q × KClick any cell to see the dot product
"I"
"love"
"AI"
"I"
1
5
3
"love"
3
3
3
"AI"
2
4
3

Select any pair of words above to see the dot product computation step by step. Each element of the Query vector pairs with the corresponding element of the Key vector, they multiply, and the results sum to produce a single attention score.

The Attention Heatmap

Before we move on, let us visualize these scores as a heatmap. Each cell’s color intensity represents how strongly one word attends to another.

Query (attending from)
Key (attending to)
Key: I
Key: love
Key: AI
Query: I
1
5
3
Query: love
3
3
3
Query: AI
2
4
3
Low attention
High attention

The heatmap makes the attention pattern immediately visible. The brightest cell is “I” attending to “love” — that score of 5 dominates. “love” is a uniform gray because it distributes attention equally. This visual pattern tells us something about the sentence structure: the pronoun reaches out to the verb, while the verb stands in the middle connecting everything.

Ilove: 70.7%
IAI: 22.3%

Select a source word above and watch particles flow to each target. The thicker the stream, the higher the attention weight. “I” sends a torrent toward “love” while barely trickling to itself.

Scaling the Scores

Raw scores can grow very large. In our tiny example the maximum is 5, but in a real model with 512-dimensional vectors, dot products can reach into the hundreds. That causes a problem.

The next step in the formula is softmax, which converts scores into probabilities using exponentials. If the scores are too large, e100e^{100} is astronomically bigger than e50e^{50}, and softmax will push all probability mass onto the highest score while assigning near-zero to everything else. The model cannot learn from such extreme distributions.

The fix is simple: divide every score by dk\sqrt{d_k}. In our case, dk=3d_k = 3, so we divide by 31.732\sqrt{3} \approx 1.732:

Scaled=Scoresdk=11.732[153333243]=[0.5772.8871.7321.7321.7321.7321.1552.3091.732]\text{Scaled} = \frac{\text{Scores}}{\sqrt{d_k}} = \frac{1}{1.732} \begin{bmatrix} 1 & 5 & 3 \\ 3 & 3 & 3 \\ 2 & 4 & 3 \end{bmatrix} = \begin{bmatrix} 0.577 & 2.887 & 1.732 \\ 1.732 & 1.732 & 1.732 \\ 1.155 & 2.309 & 1.732 \end{bmatrix}

The relative order is unchanged — “I” still attends most to “love” — but the magnitudes are smaller and more manageable for softmax.

Why dk\sqrt{d_k} specifically? The dot product of two random vectors of dimension dkd_k has an expected magnitude proportional to dk\sqrt{d_k}. Dividing by dk\sqrt{d_k} normalizes the variance back to approximately 1, keeping the softmax outputs in a stable range regardless of vector dimension.

Click to toggle scaling
Attention scores for the word "I" attending to each token
I
1.000
love
5.000
AI
3.000
Formula
scaled_score = score / sqrt(d_k)
d_k = 3, sqrt(3) = 1.732
Raw scores can be too large for softmax. Scaling keeps values stable.

Toggle the scaling above to see how dividing by dk\sqrt{d_k} compresses the scores into a range that softmax can work with. Notice that the relative ranking stays the same — only the magnitudes change.

Applying Softmax

Softmax converts each row of scaled scores into a probability distribution. Every value becomes a number between 0 and 1, and each row sums to exactly 1.

The formula for one value in a row:

softmax(xi)=exijexj\text{softmax}(x_i) = \frac{e^{x_i}}{\sum_j e^{x_j}}

Let us work through the “I” row: [0.5772.8871.732]\begin{bmatrix} 0.577 & 2.887 & 1.732 \end{bmatrix}

e0.577=1.781,e2.887=17.940,e1.732=5.651e^{0.577} = 1.781, \quad e^{2.887} = 17.940, \quad e^{1.732} = 5.651 Sum=1.781+17.940+5.651=25.372\text{Sum} = 1.781 + 17.940 + 5.651 = 25.372

Dividing each by the sum:

"I""I":1.781/25.372=0.070(7.0%)"I""love":17.940/25.372=0.707(70.7%)"I""AI":5.651/25.372=0.223(22.3%)\begin{array}{lcl} \text{"I"} \rightarrow \text{"I"} &: & 1.781 \,/\, 25.372 = 0.070 \quad (7.0\%) \\ \text{"I"} \rightarrow \text{"love"} &: & 17.940 \,/\, 25.372 = 0.707 \quad (70.7\%) \\ \text{"I"} \rightarrow \text{"AI"} &: & 5.651 \,/\, 25.372 = 0.223 \quad (22.3\%) \end{array}

The word “I” pays 70.7% of its attention to “love”, 22.3% to “AI”, and only 7.0% to itself. The softmax has amplified the differences — the original score for “love” was only about 3x the score for “I”, but the probability gap is now 10x.

For the “love” row, all scores are equal (1.732 each), so softmax produces uniform probabilities:

"love""I"=0.333"love""love"=0.333"love""AI"=0.333\text{"love"} \rightarrow \text{"I"} = 0.333 \quad \text{"love"} \rightarrow \text{"love"} = 0.333 \quad \text{"love"} \rightarrow \text{"AI"} = 0.333

For the “AI” row: [1.1552.3091.732]\begin{bmatrix} 1.155 & 2.309 & 1.732 \end{bmatrix}

"AI""I":0.168(16.8%)"AI""love":0.533(53.3%)"AI""AI":0.299(29.9%)\begin{array}{lcl} \text{"AI"} \rightarrow \text{"I"} &: & 0.168 \quad (16.8\%) \\ \text{"AI"} \rightarrow \text{"love"} &: & 0.533 \quad (53.3\%) \\ \text{"AI"} \rightarrow \text{"AI"} &: & 0.299 \quad (29.9\%) \end{array}

The full Attention Weight Matrix:

Weights=[0.0700.7070.2230.3330.3330.3330.1680.5330.299]"I""love""AI"\text{Weights} = \begin{bmatrix} 0.070 & 0.707 & 0.223 \\ 0.333 & 0.333 & 0.333 \\ 0.168 & 0.533 & 0.299 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

Each row sums to 1.0. Softmax guarantees this.

Phase: Scaled Scores (QK^T / sqrt(d_k))
I
love
AI
I
0.577
2.887
1.732
love
1.732
1.732
1.732
AI
1.155
2.309
1.732
Step 1: Raw scaled scores from dot-product similarity

Watch the softmax transformation above. The raw scores go through exponentiation (which stretches differences) and then normalization (which forces each row to sum to 1). The result is a set of clean probabilities that the model can use to mix information.

I
0.6
7.0%
love
2.9
70.7%
AI
1.7
22.3%
Probability Bars
I
love
70.7%
AI
22.3%
Distribution
love 70.7%
AI 22.3%
e^z = [0.10, 1.00, 0.32]
sum = 1.41

Drag the sliders above to see how changing the input scores reshapes the probability distribution. Try making all scores equal — the distribution flattens to uniform. Then drag one score high and watch softmax sharpen into a near-one-hot.

Computing the Final Output

The last step: we multiply the Attention Weight Matrix by the Value matrix VV. This produces the final output — one new vector for each word.

Output=Weights×V=[0.0700.7070.2230.3330.3330.3330.1680.5330.299][101120110]\text{Output} = \text{Weights} \times V = \begin{bmatrix} 0.070 & 0.707 & 0.223 \\ 0.333 & 0.333 & 0.333 \\ 0.168 & 0.533 & 0.299 \end{bmatrix} \begin{bmatrix} 1 & 0 & 1 \\ 1 & 2 & 0 \\ 1 & 1 & 0 \end{bmatrix}

For “I”:

0.070[101]+0.707[120]+0.223[110]=[0.07000.070]+[0.7071.4140]+[0.2230.2230]=[1.0001.6370.070]0.070 \begin{bmatrix} 1 \\ 0 \\ 1 \end{bmatrix} + 0.707 \begin{bmatrix} 1 \\ 2 \\ 0 \end{bmatrix} + 0.223 \begin{bmatrix} 1 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 0.070 \\ 0 \\ 0.070 \end{bmatrix} + \begin{bmatrix} 0.707 \\ 1.414 \\ 0 \end{bmatrix} + \begin{bmatrix} 0.223 \\ 0.223 \\ 0 \end{bmatrix} = \begin{bmatrix} 1.000 \\ 1.637 \\ 0.070 \end{bmatrix}

Notice: the output for “I” is dominated by the Value of “love” (weight 0.707). The second dimension (1.637) comes almost entirely from “love“‘s Value vector. This is the power of attention — “I” now carries information about “love” in its representation.

For “love”:

0.333[101]+0.333[120]+0.333[110]=[1.0001.0000.333]0.333 \begin{bmatrix} 1 \\ 0 \\ 1 \end{bmatrix} + 0.333 \begin{bmatrix} 1 \\ 2 \\ 0 \end{bmatrix} + 0.333 \begin{bmatrix} 1 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 1.000 \\ 1.000 \\ 0.333 \end{bmatrix}

For “AI”:

0.168[101]+0.533[120]+0.299[110]=[1.0001.3650.168]0.168 \begin{bmatrix} 1 \\ 0 \\ 1 \end{bmatrix} + 0.533 \begin{bmatrix} 1 \\ 2 \\ 0 \end{bmatrix} + 0.299 \begin{bmatrix} 1 \\ 1 \\ 0 \end{bmatrix} = \begin{bmatrix} 1.000 \\ 1.365 \\ 0.168 \end{bmatrix} Output=[1.0001.6370.0701.0001.0000.3331.0001.3650.168]"I""love""AI"\text{Output} = \begin{bmatrix} 1.000 & 1.637 & 0.070 \\ 1.000 & 1.000 & 0.333 \\ 1.000 & 1.365 & 0.168 \end{bmatrix} \begin{array}{l} \leftarrow \text{"I"} \\ \leftarrow \text{"love"} \\ \leftarrow \text{"AI"} \end{array}

Every word now has a new representation that is a weighted mixture of all words’ Values. The output for “I” is no longer just about “I” — it contains information from “love” and “AI”, weighted by how relevant they are. This is how the model builds context-aware representations.

d1
7%
71%
22%
I
love
AI
= 1.000
d2
86%
14%
I
love
AI
= 1.637
d3
100%
I
love
AI
= 0.070
0.070 * [1,0,1] + 0.707 * [1,2,0] + 0.223 * [1,1,0] = [1, 1.637, 0.07]
I contribution
love contribution
AI contribution

Click on each word above to see how its output vector is assembled from the Value vectors of all words. The colored segments show how much each source word contributes to each dimension of the output.

Putting It All Together

Let us review the full pipeline in one view:

Step 1: Start with input embeddings XX (each word becomes a vector).

Step 2: Project XX through three learned weight matrices to get QQ (queries), KK (keys), and VV (values).

Step 3: Compute attention scores by multiplying QQ with KTK^T. Each score measures how relevant one word is to another.

Step 4: Scale scores by dividing by dk\sqrt{d_k} to prevent softmax from producing extreme probabilities.

Step 5: Apply softmax to convert scores into attention weights (probabilities that sum to 1).

Step 6: Multiply attention weights by VV to get the final output — each word’s new context-aware representation.

Attention(Q,K,V)=softmax(QKTdk)V\text{Attention}(Q, K, V) = \text{softmax}\left(\frac{QK^T}{\sqrt{d_k}}\right) V
0
Input Embeddings
1 of 7
Each word is converted into a fixed-size vector by looking up an embedding table.
I
1010
x
love
0101
x
AI
1100
x
X = [[1,0,1,0],[0,1,0,1],[1,1,0,0]]
shape: (3, 4) -- 3 tokens, 4 dimensions each

Step through the full pipeline above. Watch data flow from raw text through embeddings, projections, scoring, scaling, normalization, and final output. Every cell in the formula has a corresponding visual step.

Self-Check

Before we finish, test your understanding:

  • Can you explain why “I” attends strongly to “love” but not to itself?
  • What would happen if we skipped the scaling step and dkd_k was very large?
  • If two words have identical Keys, how would their attention weights differ?
  • Why does each row of the attention weight matrix sum to 1?
  • What happens to the output if a word pays equal attention to all other words?

Every large language model — GPT, Claude, Gemini, Llama — runs this exact computation billions of times during inference. The numbers we used were tiny (3 words, 4 dimensions) for clarity, but the math is identical at scale. Understanding these six steps means understanding the core mechanism behind modern AI.