· 16 min read · 0 comments
Software

The Link Between Positional Encodings and Group Theory

How rotations and matrix generators turn token positions into relative information, from RoPE to exponentially damped variants.

Token positions t = 3 and s = 7 become rotations whose comparison depends only on their offset, t − s = −4. The identity R(s)ᵀR(t) = R(t − s) = exp((t − s)X) links relative position to a matrix generator: choosing X gives RoPE rotations or rotation with causal decay.

I’ve recently been trying to understand the inner workings of LLMs. Some days ago, I wrote a detailed walkthrough of how Llama 3.1 generates the next token, that follows the computation from tokenization all the way through to sampling. Writing it helped me make sense of the mechanical process, but many parts of the pipeline still felt mysterious to me, one of them being the positional encoding through which the transformer blocks get information about where tokens are relative to each other.

In Llama 3.1, rotary positional embeddings (RoPE) takes pairs of components from the query and key vectors inside each transformer block and rotates each pair by an angle that depends on the token’s position. Somehow, this lets the attention block know the relative position between tokens. But why pairs? How do those rotations make relative position show up in the attention score? And what is the mathematical structure underneath it all?

After seeing all kinds of positional encodings in papers, I often find the choices feel ad hoc, almost pulled out of the ass. Why this particular formula? Why sines and cosines? Why rotations? Even when the results look good, I still want to know: what is the first principle behind putting position information into attention? Can we start with the properties we want and arrive at different positional encodings in a principled way?

While trying to understand this and reading some of the surrounding material, I came across Alok Puranik’s Using group theory to explore the space of positional encodings for attention on the Jane Street blog. This article is my attempt to work through some of those ideas and explain them as I understand them, starting with the assumptions and then coming back to RoPE.

Where Does Position Enter the Computation?

Let’s zoom into a single transformer block in Llama. The residual stream carries one vector for each token down through the block. Two branches read from that stream and add their results back into it: the attention block, then an MLP block.

A Llama transformer block with a vertical residual stream and two residual additions. The attention branch splits into Q, K, and V. Solid RoPE blocks rotate Q and K before their dot products form attention scores. A causal mask and softmax turn these scores into weights, which multiply V. The head outputs are concatenated and projected back into the stream. A smaller RMSNorm and MLP branch makes the second update.
RoPE introduces position through the queries and keys. Values bypass the rotation and are combined using the resulting attention weights. The diagram shows the operations for a sequence; head layout is schematic, and KV sharing and caching are omitted.

The attention branch starts by normalizing the residual stream, then applying three learned projections to produce query, key, and value vectors for each token position. RoPE rotates the query and key vectors within each head, using each token’s position to set the rotation angle. The rotated queries and keys are then compared through dot products to produce the attention scores.

After scaling, a causal mask prevents each token from attending to future tokens, and softmax is applied to turn the scores into weights that multiply into the value vectors to produce a weighted sum for each query. The head outputs are concatenated and projected back to the residual stream’s width before being added to it. This follows Meta’s reference implementation.

So the place I want to focus on is those two RoPE operations. How do they actually inject information about position into the computation?

Let’s focus on just one attention head. Let qsq_s be the query at position ss and ktk_t the key at position tt. The diagram places RoPE after these vectors have been calculated but before their dot product. Writing R(s)R(s) for the rotation at position ss, the score before masking and softmax is

est=(R(s)qs)⊤(R(t)kt)dh,e_{st} = \frac{\bigl(R(s)q_s\bigr)^\top\bigl(R(t)k_t\bigr)}{\sqrt{d_h}},

where dhd_h is the dimension of a head. Each vector gets its own position-dependent rotation.

The rotated query matrix has row m highlighted and the transposed rotated key matrix has column n highlighted. Arrows lead from these vectors to their dot product divided by the square root of the head dimension, then to cell s_mn at row m and column n of the attention score matrix.
The rotated queries are stacked as rows of Q̃, and the rotated keys as columns of K̃ᵀ. Query row s and key column t produce the single score eₛₜ in S = Q̃K̃ᵀ / √dₕ, before masking and softmax.

What Should Attention Know About Position?

Before choosing a rotation, or any other encoding, it helps to ask what we want that comparison to tell us. Does attention need to know that the query is at position 12 and the key is at position 9? Or would it be enough to know that the key is three tokens behind the query?

For a relative encoding, we want our model to know the second kind of information. If we held the query and key vectors fixed and moved their positions from (12,9)(12, 9) to (112,109)(112, 109), the positional effect on their score should stay the same. The signed offset t−st-s is still −3-3. Holding the vectors fixed matters here: we’re testing the encoding, rather than claiming that moving words around in a sentence leaves the model’s representations unchanged.

The Assumptions Behind the Jane Street Analysis

The Jane Street article by Alok Puranik asks the more general question that I had in my mind: can we make some assumptions about the properties of the kind of transformations queries and keys need to undergo to inject position information? And can we use these assumptions to derive different positional encodings from first principles? Puranik’s idea was to assume four properties:

  1. Linearity in the vectors. At fixed positions, the transformations are matrices: q~s=F(s)qs\tilde q_s = F(s)q_s and k~t=G(t)kt\tilde k_t = G(t)k_t. Their positional contribution to the score is therefore F(s)⊤G(t)F(s)^\top G(t).
  2. Translation invariance. Shifting both positions equally leaves that contribution unchanged. Equivalently, F(s)⊤G(t)=H(t−s)F(s)^\top G(t) = H(t-s) for some matrix-valued function HH.
  3. Identity at zero offset. Require H(0)=IH(0)=I: comparing vectors at the same position preserves their original dot product.
  4. Continuity. Extend positions to real numbers and require H(δ)H(\delta) to vary continuously with the offset δ\delta. This is an additional assumption beyond integer token indices.

His next step is to show that these assumptions force the relative-offset matrices H(δ)H(\delta) to form a mathematical object called a one-parameter group. In particular, they obey

H(a+b)=H(a)H(b).H(a+b) = H(a)H(b).

The intuition is that moving through an offset of two tokens and then another three should have the same effect as moving through five in one go. The matrices compose in the same way that offsets add. An offset of zero does nothing, and a negative offset undoes the corresponding positive one: H(−a)=H(a)−1H(-a)=H(a)^{-1}. The “one parameter” is the single real number specifying the offset, and continuity means the transformation changes continuously as that number varies. Rotating a plane at a fixed angular speed is one example: two successive rotations add their angles, and reversing the angle undoes the rotation. Puranik’s result lets him use the established mathematics of these groups to work out which positional encodings satisfy his assumptions.

Digging into Group Theory

Before coming back to RoPE, I want to unpack that group theory bit. What is a group here, and what does it mean for a matrix to generate one?

Take all the rotations of a two-dimensional plane. Each rotation is an element of a group called SO(2)SO(2), and the operation that combines two elements is matrix multiplication. Rotating through an angle aa and then an angle bb gives another rotation, through a+ba+b. There’s an identity element, R(0)=IR(0)=I, which does nothing, and every rotation has an inverse: R(−a)R(-a) undoes R(a)R(a). Matrix multiplication is associative, so it doesn’t matter how we bracket a sequence of these operations. These are the properties that make this collection a group.

Now imagine turning the angle up continuously from zero. At zero we’re at the identity matrix. The generator tells us how the rotation matrix starts changing as we increase the angle:

J=dR(ϕ)dϕ∣ϕ=0=[0−110].J = \left.\frac{dR(\phi)}{d\phi}\right|_{\phi=0} = \begin{bmatrix}0&-1\\1&0\end{bmatrix}.

For a tiny angle ε\varepsilon, we have R(ε)≈I+εJR(\varepsilon)\approx I+\varepsilon J. Applied to a vector vv, the term JvJv gives its initial direction of motion as we begin to rotate it. The generator describes a rate of change; it isn’t itself the small rotation. In this particular example, JJ also happens to be the matrix for a quarter-turn, but its role here is as the derivative at zero.

A vector turns through angle phi, with Jv marking its initial direction of motion. The generator J, a two-by-two matrix with rows zero minus one and one zero, is scaled by phi and sent through the exponential map to the rotation matrix R(phi). The matrix exponential series reduces to cosine phi times I plus sine phi times J because J squared equals minus I. For one RoPE pair, angle phi equals position p times frequency omega, and the position generator is X equals omega J.
The generator describes the initial change at the identity. Multiplying it by an angle and applying the exponential map gives a finite rotation, an element of the group.

The next question is how to get from that initial change to a rotation through a finite angle. That’s what the exponential map does: ϕJ↦eϕJ=R(ϕ)\phi J\mapsto e^{\phi J}=R(\phi). This is a matrix exponential, defined by the same power series as the ordinary exponential, with matrix powers and the identity matrix in place of the number one:

eϕJ=∑k=0∞(ϕJ)kk!=I+ϕJ+ϕ2J22!+ϕ3J33!+⋯ .e^{\phi J}=\sum_{k=0}^{\infty}\frac{(\phi J)^k}{k!} =I+\phi J+\frac{\phi^2J^2}{2!}+\frac{\phi^3J^3}{3!}+\cdots.

Since J2=−IJ^2=-I, the powers cycle through I,J,−I,−JI,J,-I,-J. Collecting the even and odd powers gives cos⁡ϕ I+sin⁡ϕ J\cos\phi\,I+\sin\phi\,J, which is exactly the usual rotation matrix. We can also think of the exponential as the limit of many tiny steps: eϕJ=lim⁡N→∞(I+ϕJ/N)Ne^{\phi J}=\lim_{N\to\infty}(I+\phi J/N)^N.

The matrices ϕJ\phi J form a line through zero called the Lie algebra of SO(2)SO(2): the space of possible initial changes at the identity. The exponential map takes us from this space into the group. For a continuous one-parameter matrix group, the corresponding result is that H(δ)=eδXH(\delta)=e^{\delta X} for a fixed generator XX.

The earlier assumptions don’t require XX to generate rotations. A general real matrix XX can generate transformations involving scaling, rotation, or shear. If we additionally require XX to be skew-symmetric, meaning X⊤=−XX^\top=-X, then eδXe^{\delta X} is an orthogonal rotation for every δ\delta. For a RoPE pair rotating at frequency ω\omega, the angle is δω\delta\omega, so its generator with respect to position is X=ωJX=\omega J. This is a skew-symmetric generator, one particular choice within the more general matrix-group framework.

Digging into RoPE

With that structure in mind, let’s come back to how the rotations in Llama make the positional effect depend on the relative offset.

RoPE achieves this by splitting each query and key vector into pairs of components and rotating each pair in its own two-dimensional plane. At position pp, pair ii is rotated through an angle p ωip\,\omega_i, where ωi\omega_i is a fixed frequency for that pair. Queries and keys use the same frequencies, but each token’s position sets its rotation angles. These rotations make the positional effect on their dot product depend on the relative offset, as described in the RoFormer paper.

But why does rotating pairs of components work? The query and key are vectors in a much higher-dimensional space. Why split them into two-dimensional pieces instead of applying one big rotation to the whole vector? What does an NN-dimensional rotation matrix even look like?

An important property of a real skew-symmetric generator is that an orthogonal change of basis puts it into independent 2×22\times2 blocks of the form ωiJ\omega_i J, with zeros for any remaining directions. Taking the matrix exponential turns those blocks into two-dimensional rotations and leaves the remaining directions fixed. So a continuous one-parameter family of rotations in NN dimensions uses the same independent planes at every position, with a fixed frequency in each plane. This decomposition applies to rotation groups, rather than to every matrix group allowed by the earlier assumptions. RoPE (Rotary Positional Embedding) chooses its generator in this block-diagonal form, applying a rotation to each pair of coordinates in the query and key vectors. Each pair rotates at a different frequency, and the angle of rotation depends on the token’s position pp:

R(ϕ)=[cos⁡ϕ−sin⁡ϕsin⁡ϕcos⁡ϕ],ϕp,i=p ωi=pθ2i/dR(\phi)= \begin{bmatrix} \cos\phi&-\sin\phi\\ \sin\phi&\cos\phi \end{bmatrix}, \qquad \boxed{\phi_{p,i}=p\,\omega_i=\frac{p}{\theta^{2i/d}}}

where dd is the even vector dimension, ii indexes the coordinate pairs, and θ\theta is a fixed frequency-base hyperparameter. Writing cp,i=cos⁡ϕp,ic_{p,i}=\cos\phi_{p,i} and sp,i=sin⁡ϕp,is_{p,i}=\sin\phi_{p,i}, the full rotation matrix is

Rd(p)=[cp,0−sp,0⋯00sp,0cp,0⋯00⋮⋮⋱⋮⋮00⋯cp,d/2−1−sp,d/2−100⋯sp,d/2−1cp,d/2−1]⏟d×d=diag⁡ ⁣(R(ϕp,0)⏟2×2,…,R(ϕp,d/2−1)⏟2×2).\begin{aligned} R_d(p)&= \underbrace{ \begin{bmatrix} c_{p,0} & -s_{p,0} & \cdots & 0 & 0 \\ s_{p,0} & c_{p,0} & \cdots & 0 & 0 \\ \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & \cdots & c_{p,d/2-1} & -s_{p,d/2-1} \\ 0 & 0 & \cdots & s_{p,d/2-1} & c_{p,d/2-1} \end{bmatrix} }_{d\times d} \\[6pt] &=\operatorname{diag}\!\left( \underbrace{R(\phi_{p,0})}_{2\times2},\ldots, \underbrace{R(\phi_{p,d/2-1})}_{2\times2} \right). \end{aligned}

There are d/2d/2 rotation blocks along the diagonal, one for each coordinate pair; all entries outside those blocks are zero. As we move along the vector dimensions, the rotation frequencies decrease geometrically; as we move through token positions, each pair’s rotation angle increases linearly at its own frequency. We can think of this as a multi-frequency positional fingerprint, somewhat analogous to Gray code: each position corresponds to a particular configuration of rotations, with fast-changing and slow-changing components jointly representing position. Unlike Gray code, however, these are continuous, periodic signals rather than discrete bits.

The particularly useful property of these rotations comes from their group structure: composing two rotations adds their angles, so Rd(s)⊤Rd(t)=Rd(t−s)R_d(s)^\top R_d(t)=R_d(t-s). Consequently, when RoPE rotates a query at position ss and a key at position tt, their attention score becomes:

(Rd(s)qs)⊤(Rd(t)kt)=qs⊤Rd(t−s)kt.\boxed{(R_d(s)q_s)^\top(R_d(t)k_t)=q_s^\top R_d(t-s)k_t.}

Although RoPE rotates the query and key according to their absolute positions, the positional contribution to their dot product depends only on the relative displacement. This gives the transformer access to relative positional information at multiple frequencies without explicitly computing or storing pairwise positional embeddings. Mathematically, these rotations form a one-parameter group generated by a block-diagonal skew-symmetric matrix XX, with Rd(p)=epXR_d(p)=e^{pX}. RoPE is thus one example of the one-parameter groups in Puranik’s analysis: here, the generator produces rotations in independent two-dimensional planes.

Adding decay through the generator

Puranik’s analysis also considers generators that combine rotation with exponential decay. For one coordinate pair, choose

X=λI+ωJ,λ>0.X=\lambda I+\omega J,\qquad \lambda>0.

Because II and JJ commute, the relative-offset matrix becomes

H(δ)=eδX=eλδR(ωδ).H(\delta)=e^{\delta X}=e^{\lambda\delta}R(\omega\delta).

Our convention is δ=t−s\delta=t-s, key position minus query position. In causal attention, the key is at or before the query, so the lag ℓ=s−t\ell=s-t is nonnegative. The pair’s contribution to the unscaled dot product is then

qs⊤H(−ℓ)kt=e−λℓqs⊤R(−ωℓ)kt.q_s^\top H(-\ell)k_t =e^{-\lambda\ell}q_s^\top R(-\omega\ell)k_t.

The rotation encodes the offset, while the exponential gives the contribution a decaying envelope for fixed content vectors. This doesn’t guarantee that the softmax attention weight decreases, since the score also depends on content and competes with other scores.

Unlike RoPE, this construction uses different query and key transformations. Taking F(p)=e−pX⊤F(p)=e^{-pX^\top} and G(p)=epXG(p)=e^{pX} gives F(s)⊤G(t)=H(t−s)F(s)^\top G(t)=H(t-s) and preserves the dot product at zero offset. Damping both vectors identically would instead introduce dependence on the sum of their positions. The decay is directional, too. Reversing the offset produces growth, so causal masking matters here.

The diagram compares three choices of generator. Each row separates the position embeddings applied to individual queries and keys, F(p)F(p) and G(p)G(p), from the relative encoding that appears in their dot product, H(t−s)H(t-s). The paths show what happens to a fixed vector as we increase the causal lag ℓ\ell, rather than the absolute position pp.

Three generator families for one coordinate pair. RoPE uses the skew-symmetric matrix with rows zero minus omega and omega zero; both queries and keys rotate by p omega, giving relative rotation by minus omega times lag. Pure decay uses lambda times the identity; queries scale by exp minus lambda p and keys by exp lambda p, giving exp minus lambda times lag. Damped RoPE combines these matrices and transforms, giving exp minus lambda times lag times the relative rotation. A circle, radial contraction, and inward spiral illustrate the three relative transformations. Paper references identify RoFormer and xPos, including its no-rotation ablation.
Generator → query/key embeddings → relative encoding, shown for one coordinate pair. [1] Su et al., RoFormer: Enhanced Transformer with Rotary Position Embedding (2021), §3.2. [2] Sun et al., A Length-Extrapolatable Transformer (2022), §3.2; the pure-decay case is their §4.4.1 ablation.

The damped-rotation construction appears as xPos in Sun et al.’s paper. In our notation, its per-pair scale is ζi=e−λi\zeta_i=e^{-\lambda_i}, so the query transform is Fi(p)=ζipR(pωi)F_i(p)=\zeta_i^pR(p\omega_i) and the key transform is Gi(p)=ζi−pR(pωi)G_i(p)=\zeta_i^{-p}R(p\omega_i). Their product gives Hi(−ℓ)=ζiℓR(−ℓωi)H_i(-\ell)=\zeta_i^\ell R(-\ell\omega_i). Setting the rotation frequency to zero gives the pure-decay ablation. These formulas express the paper’s construction using our column-vector and offset conventions. The generator description is our mathematical interpretation of those transforms. Sun et al., §3.2 and §4.4.1.

Putting it together

So, putting it together, and trying to answer the questions I had about positional embeddings:

Prefer my writing delivered to your inbox? Subscribe here.

Correspondence

Reader Comments & Discussion

No comments yet. Be the first to share your thoughts.

Join the Discussion

Kept private
Live Preview Markdown & LaTeX

Start typing to see how your comment will render.

Complete the security check above to enable submission

Comments are moderated and will appear after review.

© 2025 Ashwin Narayan. All rights reserved.