Positional Encoding
Injecting order back into a mechanism that only sees content, not sequence position
Injecting order back into a mechanism that only sees content, not sequence position
Self-attention computes relevance purely from token content — shuffle the input tokens and the mechanism just relabels, with no built-in sense of order. Positional encoding adds a position-dependent vector to each token embedding so the model gets order information back.
Without positional encoding, a Transformer would process "dog bites man" and "man bites dog" identically at the level of self-attention's content-matching — a disaster for language, where order carries meaning. Every standard Transformer (encoder or decoder) needs some form of positional information injected before or during attention. This is one of the clearest differences between Transformers and RNNs: an RNN gets order "for free" because it processes tokens one at a time in sequence; a Transformer processes all tokens in parallel, so it has to be handed order explicitly, as data, rather than getting it from the shape of the computation itself.
Attention(Q,K,V) = softmax(QK^T/√d_k)V is computed purely as a function of the set of token
vectors fed in — it has no term anywhere that encodes "this token is 3rd" versus "this token is
7th." Attention ko khud se pata nahi hota ki kaun pehle aaya kaun baad mein — bas content dekh ke
weight deta hai. So before the input reaches attention, a positional encoding vector — one per
position — is added elementwise to the token embedding, giving each position a distinct, fixed
"fingerprint" that attention can then learn to use.
For each position pos in the sequence and each embedding dimension pair (2i, 2i+1):
2i gets a sine value.2i+1 gets a cosine value.i (early dimension pairs) gives high-frequency waves that change fast as pos increases;
high i (later pairs) gives low-frequency waves that change slowly — like a clock with many hands
moving at different speeds, giving every position a unique combined pattern.d_model stays unchanged.PE(pos, 2i) = sin(pos / 10000^(2i/d_model))
PE(pos, 2i+1) = cos(pos / 10000^(2i/d_model))
pos — the token's position in the sequence (0, 1, 2, ...).i — the dimension-pair index, ranging from 0 to d_model/2 − 1.d_model — the embedding dimension.10000 — a fixed base controlling the range of wavelengths across dimension pairs.(2i, 2i+1) encodes position as a point on a circle of a particular frequency, via
sine on the even index and cosine on the odd index.Why sine and cosine, not just one: for a fixed offset k, sin(pos+k) and cos(pos+k) can
each be expanded (angle-addition identities) as a linear combination of sin(pos) and cos(pos),
with coefficients that depend only on k, not on pos. That means PE(pos+k) is a linear
function of PE(pos) for any fixed offset k — which is exactly what lets the model's linear
attention computations learn to pick up on relative position, not just absolute position. Using
sine alone would only give one coordinate of that rotation, not the full, invertible pair.
Alternative: learned positional embeddings — a trainable embedding table indexed by position, just like a token embedding table — are used by some models (e.g. BERT, GPT-2) instead of the fixed sinusoidal formula. They're simpler to implement, but a model trained this way has no principled way to handle a position index it never saw during training, whereas the sinusoidal formula can be evaluated at any position since it's just a deterministic function.
Let d_model = 4, so i ∈ {0, 1}. For position pos = 1:
i=0: PE(1,0) = sin(1 / 10000^0) = sin(1) ≈ 0.8415; PE(1,1) = cos(1) ≈ 0.5403i=1: PE(1,2) = sin(1 / 10000^0.5) = sin(1/100) = sin(0.01) ≈ 0.0100;
PE(1,3) = cos(0.01) ≈ 0.9999So PE(pos=1) ≈ [0.8415, 0.5403, 0.0100, 0.9999].
For pos = 2, the first pair changes fast (sin(2) ≈ 0.9093, cos(2) ≈ −0.4161) while the second
pair barely moves (sin(0.02) ≈ 0.0200, cos(0.02) ≈ 0.9998) — exactly the "fast dimension, slow
dimension" behaviour described above.
d_model
does not grow.10000 is a hyperparameter of the original formula, not a universal mathematical constant — it
just controls the spread of wavelengths.pos (and i, d_model), never on
token identity.Positional encoding is a deterministic sine/cosine fingerprint, added per position, that gives attention — which only ever sees content — order information for free, and the sine+cosine pairing is specifically what makes relative position a linear, learnable operation.