• English
  • Vectors and embeddings

    After tokenization, the text is a list of integers: The cat sat becomes [976, 9059, 10139]. A neural network can only add and multiply numbers, so the obvious idea is to feed it those IDs directly. That does not work, because an ID is only a position in the vocabulary list, decided by the order in which the tokenizer happened to learn its pieces. Here are real IDs from the GPT-4o tokenizer:

    TokenID
    ·dog6,446
    ·cat9,059
    ·catalog20,913
    ·kitten114,502

    By these numbers, "catalog" is about nine times closer to "cat" than "kitten" is. Any arithmetic the network did on IDs would be arithmetic on accidents of numbering, and nothing it learned about "cat" would carry over to "kitten".

    What the model needs instead is a description of each token in which similar tokens get similar numbers. One number cannot do that: a kitten is alive, an animal, a cat, young, small, and much more. So every token gets a whole list of numbers, a vector, with room for many aspects at once.

    What the numbers mean

    Imagine filling in a character sheet for every word: is it alive? an animal? a cat? young? royal? female? a machine? One number answers each question. Words with similar meanings get similar sheets: "cat" and "kitten" differ only in the "young" row, while "car" shares almost nothing with either.

    Figure 3.1 · What the numbers in a vector mean
    🌱🐾🐱🍼👑♀⚙️
    cat0.90.90.90.10.00.00.0
    kitten0.90.90.90.90.00.00.0
    dog0.90.90.10.10.00.00.0
    puppy0.90.90.10.90.00.00.0
    king0.90.20.00.10.90.00.0
    queen0.90.20.00.10.90.90.0
    car0.00.00.00.00.00.00.9

    🌱 living🐾 animal🐱 feline🍼 young👑 royal♀ female⚙️ machine

    Every number answers one question about the word. You can read the table like a character sheet.

    Cosine similarity to “cat”
    kitten · 0.900.90
    dog · 0.860.86
    puppy · 0.740.74
    king · 0.500.50
    queen · 0.410.41
    car · 0.000.00
    Each row is one word's vector, each column one number. Pick a word to see which words have the most similar vectors (scored from −1 to 1 by cosine similarity, explained below). Then switch to the learned view: the numbers change completely, yet every similarity stays exactly the same.

    Real models use the same idea with one important twist: nobody chooses the questions. The numbers start out random, and training adjusts them step by step, keeping whatever helps predict the next token. Tokens used in similar ways end up with similar vectors, because that makes the prediction easier. The result looks like the learned view in the figure.

    That view is the same sheet after a random turn of the whole space: turning mixes every number into every other, but leaves the angles between the vectors alone, so every similarity survives. The information is there, just spread across all the numbers at once. A single number, say number 1,234 of the vector for ·cat, usually means nothing you could put a name to. What carries meaning is the whole pattern: the direction the vector points in. (Researchers can still find directions with readable meanings, as chapter 6 shows.)

    Lists of numbers as arrows

    Why talk about a list of numbers "pointing" somewhere? Because a vector, an ordered list of numbers such as (0.8,−1.2,0.3)(0.8, -1.2, 0.3), can be drawn. With two numbers it is an arrow on paper, from the origin to the point (x, y); with three, an arrow in a room. Two lists with similar numbers are two arrows pointing almost the same way.

    Language models use far more than three numbers:

    ModelNumbers per token (dmodeld_\text{model})
    GPT-2 small768
    Llama 3 8B4,096
    GPT-3 175B12,288

    The number with a B in a model's name is its parameter count in billions: Llama 3 8B has about 8 billion.

    You cannot picture 4,096 dimensions, but the geometry still works the same way: vectors have lengths, they point in directions, and the angle between two vectors tells you how alike they are.

    The embedding table

    So the model needs one vector for every token in its vocabulary. It stores them all in one big matrix, the embedding table, with one row per token. Turning a token into a vector is nothing more than reading its row: the ID is still useful, but only as an address that says which row to read, not as a meaning.

    Figure 3.2 · Looking up embeddings
    The0·cat1·sat2·on3·the4·mat5
    Embedding table · 8 tokens × 6 numbers
    d0d1d2d3d4d5
    0 The−0.67−0.19−1.29−0.80−0.370.86
    1 ·cat−0.19−1.26−0.47−2.300.400.70
    2 ·sat1.050.270.780.720.30−1.01
    3 ·on1.70−0.62−0.72−0.410.340.23
    4 ·the−0.30−0.86−0.210.23−0.220.16
    5 ·mat1.46−0.990.56−0.30−0.050.25
    6 .0.351.440.65−0.80−0.85−0.14
    7 ·dog−1.04−0.140.06−0.870.88−0.23
    Output · one row per token

    Empty: press play.

    1/8

    The tokenizer has turned the text into IDs. An ID is just a row number, it carries no meaning yet.

    Each token ID selects one row of the table. Stacking the rows gives a matrix with one row per token: the input to the first transformer block.

    The table for a 200,000-token vocabulary with 4,096 dimensions holds 819 million numbers, a big share of a small model's parameters. Like every other weight, the table starts out random and is learned during training.

    Lookup is a matrix multiplication

    Write token 3 as a one-hot vector: all zeros except a 1 at position 3. Multiplying it by the embedding table EE picks out row 3: multiplying a vector by a matrix scales each row of the matrix by the matching number in the vector and adds the rows up, and here every row but row 3 is scaled by 0. So "look up a row" and "multiply by EE" are the same operation, which is why the table can be trained with the same gradients (the signals training uses to nudge each number) as everything else.

    Measuring similarity: the dot product

    We keep saying "similar vectors". To compute with that, the model needs a number for how alike two vectors are. The tool it uses everywhere is the dot product: multiply matching entries and add them up.

    a⋅b=a1b1+a2b2+⋯+adbd=∣a∣ ∣b∣cos⁡θ\begin{aligned} \mathbf{a} \cdot \mathbf{b} &= a_1 b_1 + a_2 b_2 + \dots + a_d b_d \\ &= |\mathbf{a}|\,|\mathbf{b}| \cos\theta \end{aligned}

    Here ∣a∣|\mathbf{a}| is the length of the arrow (by Pythagoras, a12+⋯+ad2\sqrt{a_1^2 + \dots + a_d^2}) and θ\theta is the angle between the two arrows. The second form says what the dot product means: it is large when the vectors are long and point the same way. Dividing out the lengths leaves cos⁡θ\cos\theta, the cosine similarity, which ranges from −1-1 (opposite) through 00 (perpendicular, unrelated) to +1+1 (same direction).

    For example, take a=(3,2)\mathbf{a} = (3, 2) and b=(1,3)\mathbf{b} = (1, 3), the starting arrows in the figure below. The dot product is 3⋅1+2⋅3=93 \cdot 1 + 2 \cdot 3 = 9. The lengths are 13≈3.61\sqrt{13} \approx 3.61 and 10≈3.16\sqrt{10} \approx 3.16, so cos⁡θ=9/(3.61⋅3.16)≈0.79\cos\theta = 9 / (3.61 \cdot 3.16) \approx 0.79: the arrows are about 38° apart and point broadly the same way.

    Figure 3.3 · Dot product and cosine similarity
    ab
    a
    (3.0, 2.0)
    b
    (1.0, 3.0)
    a · b
    3.0×1.0 + 2.0×3.0 = 9.00
    |a|, |b|
    3.61, 3.16
    angle
    38°
    cos θ
    0.79
    −10+1

    pointing the same way: similar meaning

    Drag the tips of a and b (or focus one and use the arrow keys). The faint orange band is the projection of b onto a: the dot product is |a| times that shadow's length, negative when it points backwards.

    You will meet the dot product again in the very next chapters: attention is built from dot products between tokens, and the final step of the model scores every vocabulary token by a dot product with the last vector. That last step, the unembedding, is a second table with one row per vocabulary token. Many models simply reuse the embedding table for it (weight tying), so a token is scored highly when the final vector points the same way as that token's own embedding.

    Meaning becomes geometry

    Back to the claim from the start of the chapter: training gives tokens used in similar ways similar vectors. Why? Suppose "cat" and "kitten" are both often followed by "purred". The score for "purred" is a dot product with the vector the model builds from the words so far, so the easiest way to score it high after either word is to give the two words vectors that point the same way. Repeat that over billions of sentences and "cat" ends up close to "kitten", and "Paris" near "Rome". Nobody tells the model to do this; it is the cheapest way to predict the next token well.

    Even more surprising, directions pick up meaning. The step from "man" to "woman" is roughly the same arrow as the step from "king" to "queen". That is the famous analogy from word2vec (Mikolov et al., 2013), an early method that learns one fixed vector per word:

    king⃗−man⃗+woman⃗≈queen⃗\vec{\text{king}} - \vec{\text{man}} + \vec{\text{woman}} \approx \vec{\text{queen}}

    Below is a hand-built 3D space with these properties. Real embedding spaces are learned and messier, but the clusters and the parallel arrows are real phenomena. (Simplified: in real word2vec spaces the analogy holds only roughly and only for some relationships, and the nearest word is searched among all words except the three you started from, as the figure also does.)

    Figure 3.4 · An embedding space you can rotate
    Pick an analogy and watch the arrows: the offset between two words is copied onto a third, and the nearest word to where it lands is the answer. Click any word to list its nearest neighbours by cosine similarity.
    What the dimensions mean

    In this toy space the directions "female", "royal" and "young" were placed by hand. Even here they are not the axes: the step toward "female", for instance, changes all three coordinates at once. A real model's table looks like the learned view of figure 3.1: no single dimension has a clean meaning, and a direction (a mix of dimensions) is the unit of meaning. Interpretability research, the study of what goes on inside trained models, tries to find those directions.

    Same word, different vectors

    The embedding table gives every token exactly one vector, no matter where it appears. That is a static embedding. But "bank" in "the bank of the river" and "paid into the bank" are different words that share a spelling. The table cannot know which one you mean, so its vector for "bank" ends up as a compromise between both.

    The transformer fixes this as it reads. In every layer (one transformer block; a model stacks dozens of them), attention mixes information from the surrounding tokens into each token's vector (chapter 5). By the middle layers the vector for "bank" has been pulled toward "river" in one sentence and toward "money" in the other. These contextual embeddings are what the rest of the model works with.

    Figure 3.5 · Static and contextual embeddings
    bank
    rivershorewaterfishmoneyloanaccountcashbank
    river words0.73
    money words0.71

    cosine similarity

    Straight out of the embedding table, “bank” has one vector, a compromise between both meanings. It sits between the two clusters and is close to neither.

    The ghost circle is where the embedding table puts “bank”. Pick a sentence and watch context pull the vector into one of the two neighbourhoods. The bars show its cosine similarity to each group.

    This is the big difference from older word vectors like word2vec, which stopped at the lookup. In a transformer, the lookup is only the starting point.

    The same idea works for whole texts. An embedding model reads a sentence or a paragraph and outputs a single vector for all of it, typically by averaging the final token vectors or by reading one special token. It is trained so that texts with similar meaning land close together, even when they share no words: "How do I reset my password?" ends up near "I forgot my login".

    That is how semantic search works: embed every document once, embed the question, and return the documents with the highest cosine similarity. It is the retrieval half of retrieval-augmented generation, shown in chapter 15.

    Summary

    • Token IDs are arbitrary labels, so each token is described by a vector instead: a list of numbers in which similar tokens get similar values.
    • The numbers are learned, not chosen; meaning lives in the vector's direction, not in any single number.
    • Each token ID selects one learned row of the embedding table, a vector with hundreds to thousands of numbers.
    • The dot product and cosine similarity measure how much two vectors point the same way.
    • Training arranges the space so that related tokens are close and consistent relationships become parallel directions.
    • The table's vectors are static; attention turns them into contextual vectors that depend on the surrounding words.

    The embedding table has one blind spot: the vector for "dog" is the same whether it is the first word or the last. The next chapter adds position.