AI Engineer Roadmap All lessons Interactive Quiz MernStackDev GitHub

Positional Encoding

Play the interactive lesson: Positional encodingRead on GitHub
On this page
  1. Explain it like I'm new
  2. Watch it
  3. How it works
  4. Code example
  5. When to use it / when not to
  6. Common mistakes
  7. Recap
  8. Interview questions
  9. Go deeper

Level: Intermediate · Reading time: 8 min · Phase: 3 · LLM Concepts

In one line: Positional encoding adds information about each token's position, so the model can tell "dog bites man" from "man bites dog".

Before you start: Self Attention and Transformer Architecture.

Words to know:

Explain it like I'm new

Imagine cutting a sentence into word cards and throwing them in a bag. You have all the words, but not the order. Self-attention sees its input like that bag: it compares every token with every other token, and nothing in the math says which came first.

To fix this, we stamp each card with its seat number before it goes into the bag. In a transformer the "stamp" is a vector of numbers added to (or applied to) the token's embedding. Now "dog at position 0" looks different from "dog at position 2".

There are three common ways to stamp:

Watch it

Positional encoding: Attention has no sense of order, so position is added to each token.
Positional encoding: Attention has no sense of order, so position is added to each token.

It plays on a loop. Read the caption in the box, one step at a time. Want to go at your own pace? Step through it with Previous and Next.

How it works

Sinusoidal formula for position pos and dimension index i:

PE[pos, 2i]   = sin( pos / 10000^(2i / d_model) )
PE[pos, 2i+1] = cos( pos / 10000^(2i / d_model) )
  1. Each pair of dimensions is a wave with a different speed. Early dimensions change quickly between positions; later ones change slowly.
  2. Together they give each position a unique "fingerprint", like the hands of a clock (seconds, minutes, hours).
  3. The vector is added to the token embedding before the first layer.
  4. Because sin(a+b) can be written using sin(a) and cos(a), the offset between two positions is a simple linear function. This helps the model learn relative distance.

Worked example

With d_model = 4 (each vector has 4 numbers):

pos 0: [sin(0),  cos(0),  sin(0/100),  cos(0/100)] = [0.000, 1.000, 0.000, 1.000]
pos 1: [sin(1),  cos(1),  sin(1/100),  cos(1/100)] = [0.841, 0.540, 0.010, 1.000]
pos 2: [sin(2),  cos(2),  sin(2/100),  cos(2/100)] = [0.909, -0.416, 0.020, 1.000]

(10000^(2/4) = 100, which is why dimensions 2 and 3 move slowly.)

flowchart LR
    T[token embedding] --> P((+))
    S[position vector] --> P
    P --> A[first transformer layer]

Now add it. Say "dog" has the embedding [1, 0, 1, 0] (a made-up toy vector). At position 0 it becomes [1, 0, 1, 0] + [0, 1, 0, 1] = [1, 1, 1, 1]. At position 2 it becomes [1, 0, 1, 0] + [0.909, -0.416, 0.02, 1.0] = [1.909, -0.416, 1.02, 1.0]. The same word now gives two different inputs, so attention can tell the seats apart.

RoPE in one sentence: instead of adding a vector, it rotates each 2-D pair of Q and K features by pos × θ_i, so the dot product q·k depends on the distance between positions.

Code example

From llm_attention.py:

import math

def sinusoidal_positional_encoding(seq_len, d_model):
    pe = []
    for pos in range(seq_len):
        row = []
        for j in range(d_model):
            angle = pos / (10000 ** (2 * (j // 2) / d_model))
            row.append(math.sin(angle) if j % 2 == 0 else math.cos(angle))
        pe.append(row)
    return pe

for row in sinusoidal_positional_encoding(3, 4):
    print([round(v, 3) for v in row])
# [0.0, 1.0, 0.0, 1.0]
# [0.841, 0.54, 0.01, 1.0]
# [0.909, -0.416, 0.02, 1.0]

When to use it / when not to

You rarely pick this yourself; it comes with the model. It matters when you read model cards or try to extend context length.

MethodLearned?Handles longer text than training?Seen in
SinusoidalNoIn theory, quality often dropsOriginal transformer
Learned absoluteYesNo, fixed max positionsGPT-2, BERT
RoPENo (fixed rotation)Can be stretched with scaling tricksLlama and many open LLMs
ALiBiNo (distance penalty on scores)Designed to extrapolateSome open models

Common mistakes

Recap

If you remember only three things:

Interview questions

1. Why is positional information needed in a transformer? <details><summary>Answer</summary> Self-attention is permutation-equivariant: reordering the input tokens just reorders the outputs. Without position signals the model cannot distinguish different word orders. </details>

2. What is the advantage of sinusoidal over learned absolute positions? <details><summary>Answer</summary> It has no parameters, works for any position number, and relative offsets are a linear function of the encodings. Learned positions are limited to the maximum length seen in training. </details>

3. How does RoPE encode position? <details><summary>Answer</summary> It rotates pairs of features in the query and key vectors by an angle proportional to the token position. The dot product between a rotated query and key then depends on their relative distance. </details>

Go deeper

Prev: Multi Head Attention · Next: Decoder Only Models · Back to phase: Phase 3