Concept units

Embeddings: things as vectors

Intermediate

Read these first if they are new to you

The idea in one paragraph

A neural network computes only with numbers. An embedding gives each item the network reads, such as a word, a category or a 3D point, a vector of d numbers. The network learns these vectors during training, like its other weights. For items from a fixed list, the embedding is a table with one learned row per item. For items that are already numbers, such as a point's coordinates, a linear layer turns them into the vector. Picture every item as a dot in a space of d dimensions, placed where it helps the task.

A label number would invent an order that is not there

Say a network must read one of four kinds of object: cat, dog, car and truck. The simplest idea is to number them 0, 1, 2 and 3 and feed in that number. This misleads the network. A linear layer multiplies its input by weights, so it would treat "truck" as three times "dog", and "car" as halfway between "dog" and "truck". None of that is true.

An embedding avoids the problem. Each item gets its own vector, and no item's vector depends on another item's number. The network can then place cat near dog and car near truck, if that helps it.

An embedding table holds one learned row per item

An embedding table has one row for each item in the list and d columns. The number d is the embedding size. To embed an item, the network looks up its row. Real tables are large: for example, 50,000 words with d = 512. The figure uses four items and d = 2, so each row is a point you can draw.

A table with one row per item, drawn as points in the plane
Embedding table (d = 2) column 1 column 2 cat dog car truck 0.90.2 0.80.3 −0.70.6 −0.80.5 row = one item's vector column 1 column 2 1 −1 cat dog car truck
What to notice. Each row of the table is one point. In this made-up table, training has put the two animals close together and the two vehicles close together, far from the animals.

Predict first. Is "cat" closer to "dog" or to "truck"? Guess from the picture, then check with numbers.

Worked example: look up and compare
  1. Embed "dog": look up its row, [0.8, 0.3].
  2. Measure the distance from cat to dog: √((0.9 − 0.8)2 + (0.2 − 0.3)2) = √0.02 ≈ 0.141.
  3. Measure the distance from cat to truck: √((0.9 − (−0.8))2 + (0.2 − 0.5)2) = √2.98 ≈ 1.726.

Cat is twelve times closer to dog than to truck. A later layer that reads these vectors will tend to treat cat and dog alike, which the label numbers 0 and 1 could never arrange on their own.

Looking up a row is the same as a linear layer without a bias applied to a one-hot vector: a vector with a 1 in the item's place and 0 everywhere else. For dog, the one-hot vector is [0, 1, 0, 0]. Each output is a weighted sum in which only dog's weight survives, so the result is dog's row. Libraries skip the multiplication and look the row up directly; PyTorch calls the table torch.nn.Embedding.

A point already has numbers, and a linear layer lifts them to d numbers

A 3D point p = (x, y, z) is already a vector, but only of 3 numbers. Networks usually want longer vectors, such as 64 or 256 numbers, so that later layers have room to store what they learn about the point. A linear layer with weights W (d rows, 3 columns) and a bias b makes the embedding Wp + b.

Worked example: embed the point (1, 2, −1) with d = 4

Take these learned weights and bias:

Outputweight on xon yon zbiasresult
10.5−0.20.10.10.5 − 0.4 − 0.1 + 0.1 = 0.1
20.00.30.80.00 + 0.6 − 0.8 + 0 = −0.2
3−0.40.60.2−0.2−0.4 + 1.2 − 0.2 − 0.2 = 0.4
40.70.1−0.50.30.7 + 0.2 + 0.5 + 0.3 = 1.7

The point's embedding is [0.1, −0.2, 0.4, 1.7]. Every point in a cloud goes through the same layer, with the same weights.

Once every item has a vector of the same size d, the network treats them all alike. Each such vector is called a token. A model of a point cloud often makes one token per point, or one per small group of nearby points.

A linear layer gives nearby points nearby embeddings. The layers after it then find fine detail, such as a sharp change between two close points, slow to learn. Many models therefore first expand each coordinate into waves of several frequencies, called Fourier features, and embed those instead.

Training moves the vectors to where they help

At the start of training, the table and the weights hold small random numbers, so cat and truck are as close as cat and dog. Each training step nudges every weight that took part, table rows included, in the direction that lowers the error (see gradient descent). Items that the task treats alike tend to drift together.

The flat picture is a cartoon

Real embeddings have tens to thousands of numbers, not 2. Their single numbers rarely have a meaning a person could name. "Similar items end up close" is a common result of training, not a guarantee: it happens only where the task rewards it. A row for an item that never appears in training keeps its random starting values.

embed.py

import numpy as np

E = np.array([[ 0.9, 0.2],    # cat
              [ 0.8, 0.3],    # dog
              [-0.7, 0.6],    # car
              [-0.8, 0.5]])   # truck

one_hot = np.array([0, 1, 0, 0])
print(E[1], one_hot @ E)      # look up dog's row, two ways

def dist(a, b):
    return np.linalg.norm(E[a] - E[b])
print(round(dist(0, 1), 3), round(dist(0, 3), 3))

W = np.array([[0.5, -0.2, 0.1], [0.0, 0.3, 0.8],
              [-0.4, 0.6, 0.2], [0.7, 0.1, -0.5]])
b = np.array([0.1, 0.0, -0.2, 0.3])
print(W @ np.array([1.0, 2.0, -1.0]) + b)   # embed a 3D point
[0.8 0.3] [0.8 0.3]
0.141 1.726
[ 0.1 -0.2  0.4  1.7]

Check yourself

  1. An embedding table covers 50,000 words with d = 512. How many numbers does training have to learn for it?

    Answer

    50,000 × 512 = 25,600,000: one learned number for each cell of the table.

  2. Work a similar problem. Using the weights and bias of the worked example, embed the point (0, 1, 0).

    Answer

    Only the weights on y count: [−0.2, 0.3, 0.6, 0.1]. Add the bias [0.1, 0.0, −0.2, 0.3] to get [−0.1, 0.3, 0.4, 0.4].

  3. Why is feeding the item numbers 0, 1, 2, 3 into a linear layer a poor idea, while a one-hot vector works?

    Answer

    A single number forces an order and a spacing: the layer's output changes by the same step from item 0 to 1 as from 1 to 2. A one-hot vector gives each item its own input, so each item gets its own learned weights, which is exactly a row of an embedding table.

Go further

Optional background, for readers who want more than this page.

Where this shows up

Units that build on this one