Attention calculator

Drag queries, keys, and values on a plane and watch scaled dot-product attention compute scores, weights, and outputs for every token.

AdvancedExplained in Attention, step by step

Attention, one query at a time

Pick a token. Its query is compared with every key, the scores become weights, and the weights mix the values.

Choose the query token
k Thek catk satk onk thek matq sat

Drag the arrow tips. A key that points the same way as the query gets a high score.

Scores and weights for the query "sat" against every key
Keyq · k÷ √2softmax weight
-2.52-1.780%
5.884.1676%
2.281.616%
-0.96-0.681%
-3.48-2.460%
3.782.6717%

qsat · kcat = 2.40 × 2.20 + 0.60 × 1.00 = 5.88

output = Σ weight × v = (1.54, 0.48)

All six queries at once: the attention weight matrix, softmax(QKᵀ/√d_k)

Attention weights. Rows are queries, columns are keys. Select a row to make it the current query.
query ↓ key →Thecatsatonthemat
0.010.620.110.020.010.23
0.040.160.580.190.010.01
0.000.760.060.010.000.17
0.010.220.010.010.010.74
0.010.310.030.010.020.62
0.090.050.500.330.030.00

Shapes: Q, K, V are 6 × 2. QKᵀ is 6 × 6, one row per query. The output is 6 × 2, one mixed vector per token.

The plane shows
Query tokensat
Attends most tocat, 76%
Output vector(1.54, 0.48)

Challenges

0 of 4 complete

  1. With scaling on, make the chosen query give at least 95% of its weight to a single key. (not yet)
  2. Make the chosen query weigh all six tokens equally. (not yet)
  3. Make two different tokens get exactly the same weight from every query. (not yet)
  4. Without moving any query or key, make the output for sat point down and to the right (x above 0, y below 0). (not yet)

Try this

  • Pick mat as the query. Which key does it favor, and what happens to the output when you drag that key’s value somewhere new?
  • Drag two keys to exactly the same point. Their weights become equal for every query. (Same direction is not enough: a longer key gets a larger score.)
  • Turn off scaling and compare the matrix with scaling on. Every row gets sharper.
Scaled dot-product attention in a few linesPython with NumPy
import numpy as np

tokens = ["The", "cat", "sat", "on", "the", "mat"]
# The demo's starting vectors: one row per token, two numbers each.
Q = np.array([[1.6, 0.4], [0.3, 2.0], [2.4, 0.6], [1.5, -1.2], [1.4, -0.8], [-0.5, 2.0]])
K = np.array([[-1.2, 0.6], [2.2, 1.0], [0.4, 2.2], [-0.8, 1.6], [-1.4, -0.2], [1.8, -0.9]])
V = np.array([[0.2, -1.0], [1.8, 0.8], [-0.4, 1.9], [-1.5, 0.3], [0.3, -1.1], [1.2, -1.4]])

def softmax(x):
    e = np.exp(x - x.max(axis=-1, keepdims=True))
    return e / e.sum(axis=-1, keepdims=True)

d_k = K.shape[1]
scores = Q @ K.T / np.sqrt(d_k)  # 6 x 6: every query against every key
weights = softmax(scores)        # each row sums to 1
output = weights @ V             # each row is a weighted average of the values

i = tokens.index("sat")
print("sat attends to:", ", ".join(f"{t} {w:.0%}" for t, w in zip(tokens, weights[i])))
print("output for sat:", np.round(output[i], 2))
print("shapes:", scores.shape, output.shape)
sat attends to: The 0%, cat 76%, sat 6%, on 1%, the 0%, mat 17%
output for sat: [1.54 0.48]
shapes: (6, 6) (6, 2)

Try "embedding", "softmax", "overfitting", or "backpropagation".