Linear algebra for LLMsPart 6: The rest of the transformer

RoPE

7 min

Rotate queries and keys by position

q~m=R(mθ) qmk~n=R(nθ) kn\displaystyle \tilde q_m = R(m\theta)\, q_m \qquad \tilde k_n = R(n\theta)\, k_n

Take the 2D rotation from Part 3. The query of the token at position mm is turned by mθm\theta; the key at position nn by nθn\theta. Values aren’t rotated. Nothing is added to the embeddings.

Write

RoPE: q~m=R(mθ)qm\tilde q_m = R(m\theta)q_m, k~n=R(nθ)kn\tilde k_n = R(n\theta)k_n. Values untouched.

The score sees only the distance

q~m⋅k~n=qm⊤R(mθ)⊤R(nθ) kn\displaystyle \tilde q_m \cdot \tilde k_n = q_m^\top R(m\theta)^\top R(n\theta)\, k_n
=qm⊤R((n−m)θ) kn\displaystyle = q_m^\top R\big((n - m)\theta\big)\, k_n

The identity from Part 3: the two rotations combine into one by the difference of the angles. The same pair of tokens gets the same score at positions 3 and 7 as at 103 and 107. Attention learns relative position for free.

Write

q~m⋅k~n=q⊤R((n−m)θ) k\tilde q_m \cdot \tilde k_n = q^\top R((n - m)\theta)\,k: depends on n−mn - m only.

Picture it in 2D

q at m = 1k at n = 3

With θ=0.4\theta = 0.4: the query at position 1 is turned 0.4 rad, the key at position 3 is turned 1.2 rad. Move both tokens along by any number of positions and both arrows turn by the same extra angle, so the angle between them, and their dot product, stays the same.

Many pairs, many frequencies

(x1,x2), (x3,x4), …\displaystyle (x_1, x_2),\ (x_3, x_4),\ \dots
pair i turns by m θi\displaystyle \text{pair } i \text{ turns by } m\,\theta_i
θi=b−2i/dh,i=0,1,…,dh2−1\displaystyle \theta_i = b^{-2i/d_h}, \quad i = 0, 1, \dots, \tfrac{d_h}{2} - 1

A head of width dhd_h is cut into dh/2d_h/2 pairs, and each pair gets its own speed. Pair 0 turns 1 radian per position; the last pairs turn very slowly. Like the hands of a clock, fast pairs tell nearby positions apart and slow ones cover long distances. The original paper used b=10,000b = 10{,}000; Llama 3 uses b=500,000b = 500{,}000 for longer contexts.

Write

θi=b−2i/dh\theta_i = b^{-2i/d_h}: pair 0 fast (1 rad/position), later pairs slower.

A tiny head

dh=4, b=10,000 ⁣:θ0=1,θ1=10,000−1/2=0.01\displaystyle d_h = 4,\ b = 10{,}000\!: \quad \theta_0 = 1, \quad \theta_1 = 10{,}000^{-1/2} = 0.01
at position m=3 ⁣:angles 3 and 0.03 rad\displaystyle \text{at position } m = 3\!: \quad \text{angles } 3 \text{ and } 0.03 \text{ rad}

✏️ Your turn

Your angle

dh=4,b=100\displaystyle d_h = 4, \quad b = 100

What is θ1\theta_1, and how far does pair 1 turn at position m=10m = 10?

Work it out on paper, then go to the next card to check.

Answer

θ1=100−2/4=100−1/2=0.1\displaystyle \theta_1 = 100^{-2/4} = 100^{-1/2} = 0.1
m θ1=10×0.1=1 rad\displaystyle m\,\theta_1 = 10 \times 0.1 = 1 \text{ rad}

How code does it

def rotate_half(x):
    x1, x2 = x.chunk(2, dim=-1)     # the two halves
    return torch.cat((-x2, x1), dim=-1)

# cos, sin: (T, d_h), one angle per position and pair
q = q * cos + rotate_half(q) * sin
k = k * cos + rotate_half(k) * sin

In a transformer

No rotation matrix is ever built: each pair’s 2×2 rotation is written out as xcos⁡+(rotated x)sin⁡x\cos + (\text{rotated } x)\sin. Hugging Face’s Llama code pairs dimension ii with i+dh/2i + d_h/2 instead of neighbours, which is the same idea with the dimensions listed in a different order.

📌 Recap

RoPE in one card

  • Rotate each pair of query and key dimensions by mθim\theta_i, the position times the pair’s speed.
  • q~m⋅k~n\tilde q_m \cdot \tilde k_n depends only on n−mn - m.
  • θi=b−2i/dh\theta_i = b^{-2i/d_h}; b=10,000b = 10{,}000 originally, 500,000 in Llama 3.
  • Code applies it as xcos⁡+rotate_half⁡(x)sin⁡x\cos + \operatorname{rotate\_half}(x)\sin.

Write

The four lines above.