Chapter 2 · About 12 minutes

Embeddings and position

Each token becomes a list of 128 numbers, plus a second list for where it sits in the text.

You will learn

  • Say what an embedding is and where its numbers come from
  • Explain why similar words end up with similar numbers
  • Work out a dot product by hand
  • Say how the model knows the order of the tokens

Each token becomes a list of numbers

Show the numbers for

Number 1 of 128. Token 0.008 + position -0.385 = -0.377

Blue is below zero and orange is above, and paler means closer to zero. Biggest is number 76 at 0.126. Smallest is number 5 at -0.209.

Pick a token to see its 128 numbers.

A grid of 128 colored cells, one per number in the picked token's list. Arrow keys move between cells and the value is shown below.

Story

An id like 665 is only a label, and its size means nothing. So each id picks one row from a big table, a list of 128 numbers called an Embedding The list of numbers a model uses for a token. Each token id picks one row of a learned table. Open the glossary. A token gets the same list every time it appears.

These numbers start out random. Training nudges them, bit by bit, until they help the model guess well. Tap a cell to see one number.

Numbers

The table has 4,096 rows, one for each token, and 128 numbers in each row. That is 524,288 numbers, about 2 in every 5 numbers the model learned.

The first five numbers for “Lily” are 0.008, 0.006, -0.046, 0.001 and -0.209. A list of numbers like this is called a Vector A list of numbers. Ours have 128 numbers each. Open the glossary.

Formula

Looking up a row of the embedding table WEW_E gives the token’s vector.

xi=WE[ti],WE∈R4096×128\mathbf{x}_i = W_E[t_i], \qquad W_E \in \mathbb{R}^{4096 \times 128}

The lookup is the same as multiplying a one-hot vector, all zeros except a 1 at tit_i, by WEW_E.

Code

const lily = rowView(model.wte, 665); // 128 numbers
trace.tokenEmbeddings; // one row per token, 6 × 128

Which word has numbers most like "happy"?

Similar words get similar numbers

Closest to space girl. space boy 0.74, space child 0.58, space daughter 0.57, space kid 0.55, space lady 0.54

  1. space boy0.74
  2. space child0.58
  3. space daughter0.57
  4. space kid0.55
  5. space lady0.54
Pick a word to see the tokens with the most similar numbers.

Word chips to pick from, and a list of the five tokens whose numbers are most like the picked word's, each with a similarity score from -1 to 1.

Story

Nobody tells the model what words mean. Still, after training, words used in similar ways end up with similar lists (Mikolov et al., 2013). “Girl” lands near “boy”, “red” near the other colors, and “ran” near “run” and “walked”.

The model found this on its own, because it helps to guess the next word. Pick a word to see its closest tokens.

Numbers

The score is the cosine similarity. 1 means the two lists point the same way, 0 means they have nothing in common and -1 means they point opposite ways.

“·girl” and “·boy” score 0.74. “·three” and “·3” score 0.88, so the model uses the word and the digit almost alike. (“·3” is one of the few numbers with a token of its own.) “·Lily” and “Lily” at the start of a text score 0.76, even though the Tokens chapter showed they are two different tokens.

Formula

Cosine similarity divides the Dot product A way to compare two lists of numbers. Multiply the numbers in matching places and add up the results. Open the glossary of two vectors by their lengths, so only their direction counts.

cos⁡(a,b)=a⋅b∥a∥ ∥b∥\cos(\mathbf{a}, \mathbf{b}) = \frac{\mathbf{a} \cdot \mathbf{b}}{\lVert \mathbf{a} \rVert \, \lVert \mathbf{b} \rVert}

Code

const dot = (a, b) => a.reduce((sum, x, k) => sum + x * b[k], 0);
const cosine = (a, b) => dot(a, b) / Math.sqrt(dot(a, a) * dot(b, b));
cosine(rowView(model.wte, 477), rowView(model.wte, 497)); // ·girl and ·boy, 0.74

Like places on a map

Think of each word as a town on a map, with towns that are used alike sitting close together. Where this breaks. A map has 2 directions. These lists have 128, and single numbers rarely mean anything simple on their own, like size or color.

Comparing two lists

Story

To compare two lists, multiply the numbers in matching places and add up the results. This is the Dot product A way to compare two lists of numbers. Multiply the numbers in matching places and add up the results. Open the glossary.

It is big when both lists have large numbers in the same places with the same signs. It is near zero when they have nothing in common, and below zero when the signs disagree. The dot product comes back in the attention chapter, where it decides which tokens look at which.

Numbers

Take (1, 2, 3) and (4, 0, -1). Multiply place by place to get 4, 0 and -3. Add them up to get 1.

Formula

a⋅b=∑k=1dak bk\mathbf{a} \cdot \mathbf{b} = \sum_{k=1}^{d} a_k \, b_k

For our embeddings d=128d = 128.

Code

const dot = (a, b) => a.reduce((sum, x, k) => sum + x * b[k], 0);
dot([1, 2, 3], [4, 0, -1]); // 1

Each place gets numbers too

Show the numbers for

Number 1 of 128. Token 0.014 + position -0.249 = -0.235

Blue is below zero and orange is above, and paler means closer to zero. Biggest is number 68 at 0.234. Smallest is number 1 at -0.249.

Switch between the token, its place and the two added together.

A grid of 128 colored cells, one per number in the picked token's list. Arrow keys move between cells and the value is shown below.

Story

So far, “play” gets the same list wherever it appears. But order matters. “Lily saw Max” and “Max saw Lily” use the same words.

So the model also learns one list of 128 numbers for each place in the text, called a Position embedding A list of numbers for each place in the text, added to the token's list so the model knows the order. Open the glossary. It adds the place’s list to the token’s list, number by number. That sum is what the first layer reads.

Numbers

Our model has 128 position lists, one for each place, so it reads at most 128 tokens at a time. Nearby places get similar lists. Places 2 and 3 score 0.98, while places 2 and 51 score -0.22.

Our model learns these lists, like GPT (Radford et al., 2018) and GPT-2. The original transformer used fixed sine and cosine waves instead (Vaswani et al., 2017).

Formula

hi=WE[ti]+WP[i−1],WP∈R128×128\mathbf{h}_i = W_E[t_i] + W_P[i-1], \qquad W_P \in \mathbb{R}^{128 \times 128}

Places count from 1 but table rows count from 0, so place ii uses row i−1i-1.

Code

trace.positionEmbeddings; // one row per place, 6 × 128
trace.embeddings; // tokenEmbeddings + positionEmbeddings

Recap

  • Each token id picks a row of 128 numbers from a table. That row is its embedding.
  • Training tunes the rows, so words used in similar ways get similar numbers.
  • The dot product compares two lists by multiplying matching numbers and adding them up.
  • Each place in the text has its own list too, added to the token's list.

Go deeper