Embeddings
The bridge between token IDs and the learned numeric representations that models actually use. Understand what an embedding is in vector terms, how it relates to the topics you've just studied, and where the full embedding story continues.
Embeddings: The Scholar's Memory Drawers
The Embedding Matrix is a grand cabinet of 128,000 numbered drawers. Opening drawer #4127 ("cat") reveals a velvet tray holding 4,096 fine tuning knobs. These knobs were gradually nudged and perfected during the scholar's years of pre-training reading so that drawers of related concepts (e.g., "kitten", "feline") now share strikingly similar numeric settings.
IntroductionWhat is an embedding in vector terms?
An embedding is the dense vector a token retrieves from a learned lookup table. When a model processes the word cat, it first converts it to a token ID (say, 4127), then looks up row 4127 in a large matrix called the embedding table. The result is a compact list of floating-point numbers — a vector — that the model uses as the token's representation.
- The symbolic world:
"cat"→4127(a discrete integer index) - The geometric world:
4127→[0.12, -0.41, 0.77, 0.03, …](a continuous vector in ℝᵈ) - This is the bridge from tokenization into the vector space you've been studying.
One-hot vector (before embeddings)
Vocab-length. One 1, rest 0. No semantics. 50,000-element sparse vector per token. Impractical for matrix math.
Embedding vector (what models use)
Fixed-width d (e.g. 768). All floats. Learned. Geometrically encodes patterns. 768-element dense vector per token. GPU-efficient.
WhyWhy not feed raw IDs or one-hot vectors to the model?
Raw token IDs are just arbitrary integers. Token ID 4127 has no mathematical relationship to token ID 4128 — the numbers are random addresses, not magnitudes. Feeding raw IDs to a neural network layer would impose a false ordering on tokens that have none.
- IDs have no magnitude meaning: ID 9000 is not "more" of anything than ID 1. Multiplying by an ID number is meaningless.
- One-hot vectors are vocab-sized: A 50,000-token vocabulary means 50,000-dimensional vectors. Every dot product involves 50,000 multiplications — almost all of which are multiplying by 0. Grossly wasteful.
- Dense embeddings are compact: 768 floats per token. 98.5% less data. 100% non-zero. Every dimension contributes to every computation.
- Dense embeddings are learnable: The embedding table is a parameter matrix — it starts random and updates during training to encode useful patterns.
The Embedding TableShape, size, and structure: E ∈ ℝ^(V×d)
The embedding table is a 2D matrix with one row per vocabulary token and one column per embedding dimension. The shape is $E \in \mathbb{R}^{V \times d}$, where:
- $V$ = vocabulary size (e.g. 50,257 for GPT-2; 30,522 for BERT-base)
- $d$ = embedding dimension (e.g. 768 for BERT-base, 1024 for GPT-2 medium)
- $x_i = E[t_i]$ — the embedding for token $t_i$ is the row at index $t_i$
Here is what the table looks like conceptually. Each row is the full $d$-dimensional vector for one token:
dim₀ dim₁ dim₂ dim₃ … dim₇₆₇ row 0 [PAD] 0.00 0.00 0.00 0.00 … 0.00 row 101 [CLS] 0.34 -0.12 0.87 -0.45 … 0.21 row 102 [SEP] -0.11 0.56 -0.23 0.78 … -0.09 row 1996 cat 0.12 -0.41 0.77 0.03 … 0.55 row 3899 dog 0.14 -0.38 0.74 0.07 … 0.52 row 2482 car -0.65 0.22 -0.31 0.88 … -0.44 … … … … … … …
How It WorksFrom text to vectors: the full pipeline
Embedding lookup is deliberately simple: it is a table access, not a computation. No arithmetic happens at lookup time — the model just reads the pre-stored row.
["the", "cat", "sat"]
[101, 4127, 2938] (vocabulary lookup)
Connection to Vector SpaceWhere the vector concepts you learned apply directly
Every embedding is a point in $\mathbb{R}^d$. Once tokens are embedded, all the geometric tools you've studied in this roadmap branch apply directly and are used constantly inside the model:
| Vector concept | How it applies to embeddings | Where used |
|---|---|---|
| Cosine similarity | Measure how semantically related two token embeddings are | Nearest-neighbour search, RAG retrieval, word similarity tasks |
| Dot product | Attention score between query and key vectors (both derived from embeddings) | Self-attention in every transformer layer |
| Euclidean distance | Direct distance in embedding space; less common than cosine for semantic tasks | Some clustering and retrieval systems |
| Vector arithmetic | king − man + woman ≈ queen (analogies encoded as directions in embedding space) | Word2vec analysis, probing classifiers |
| Dimensionality | Each embedding has d dimensions (768, 1024, etc.) that define the geometry | Architecture design: d = transformer hidden size |
What Embeddings Are NotCorrecting the most common misconceptions
Embeddings are commonly misunderstood. Here is a precise list of what they are and what they are not:
❌ Not a dictionary definition
An embedding is not a semantic definition of a word. It is a numeric pattern that helps a specific model perform its training objective. Two models trained on different tasks will have different embeddings for the same token.
❌ Not a fixed fact about a word
The embedding for "bank" in BERT is a single static vector. But "bank" (financial) and "bank" (river) have completely different meanings — the static embedding averages over both. Context changes meaning; static embeddings cannot capture this.
❌ Not interchangeable across models
Different models train different embedding tables. An embedding from GPT-2 is not compatible with BERT's embedding space. They have different dimensions, different vocabularies, and different geometric structures.
✅ Learned numeric patterns
Embeddings are learned parameters. They start random and update via gradient descent. After training, similar-context tokens have similar embeddings — but only in the geometry learned by that specific model on that specific training data.
CodeEmbedding lookup from scratch — and with PyTorch
Start with pure Python to see that embedding lookup is nothing more than array indexing, then see the PyTorch equivalent that adds gradient tracking and batch support:
import random
# ── Pure Python: embedding table as a 2D list ────────────────────────────────
VOCAB = {"[PAD]": 0, "[UNK]": 1, "[CLS]": 2, "[SEP]": 3, "cat": 4, "dog": 5, "car": 6}
V = len(VOCAB) # vocabulary size
D = 8 # embedding dimension (tiny, for illustration)
random.seed(42)
# Each row is a token's embedding — initialised uniformly at random
E = [[round(random.uniform(-1, 1), 3) for _ in range(D)] for _ in range(V)]
def embed(token: str) -> list[float]:
"""Look up the embedding for a single token."""
idx = VOCAB.get(token, VOCAB["[UNK]"]) # unknown tokens → [UNK] row
return E[idx] # row selection — O(1) table lookup
print(embed("cat")) # e.g. [0.304, -0.719, 0.218, ...]
print(embed("dog")) # different values, but after training would be similar to cat
# ── PyTorch: nn.Embedding (what production models use) ───────────────────────
import torch
import torch.nn as nn
V_real = 50257 # GPT-2 vocabulary size
D_real = 768 # GPT-2 small embedding dimension
# Create the embedding table — weights initialised randomly, updated by backprop
embedding_table = nn.Embedding(num_embeddings=V_real, embedding_dim=D_real)
# Simulate a token ID sequence: ["cat", "sat", "on", "the", "mat"]
token_ids = torch.tensor([4127, 2938, 2006, 1996, 13523]) # hypothetical IDs
# Embedding lookup: each ID → corresponding row → shape (5, 768)
vectors = embedding_table(token_ids)
print(vectors.shape) # torch.Size([5, 768])
# nn.Embedding is differentiable — gradients flow back into the table during training
# The table's .weight attribute is the V×D matrix, accessible for inspection:
print(embedding_table.weight.shape) # torch.Size([50257, 768])
What the scratch code shows
Embedding lookup is array indexing. A table is a 2D list; a lookup is table[token_id]. No matrix multiplication, no activation function — just row selection.
What PyTorch adds
Gradient tracking (the table is a parameter), batching (process multiple sequences at once), GPU placement (.to('cuda')), and integration with the rest of the model's backward pass.
Go DeeperThis page is the bridge — the full story continues elsewhere
This page gives you the vector-world view of embeddings: what the table is, what the shape means, how lookup works, and how it connects to distance, similarity, and attention. That is enough to understand how vectors flow through a transformer.
The full embedding story — how embeddings are learned, what word2vec and GloVe taught us, contextual vs static representations, sentence embeddings, and the deep geometry of embedding space — is in the dedicated Embeddings roadmap branch.
→ Full Embeddings Roadmap
Word2vec · GloVe · FastText · Sentence embeddings · Embedding-space geometry · Fine-tuning. Start here when you reach the Embeddings branch.
→ How Embeddings Are Learned
Next in this vectors branch. Distributional hypothesis · gradient descent on the embedding table · why similar-context tokens end up with similar vectors.
Also worth knowing what comes immediately after embeddings in the transformer pipeline:
Feynman ChallengeCan you explain it simply?
Explain embeddings using the "hotel register" metaphor:
- The embedding table is a hotel register. Every room has a number (token ID) and a detailed guest profile page (the embedding vector).
- When a token arrives, the model looks up its room number — it reads the profile page, not the room number.
- The profile has 768 fields (embedding dimensions) — things like "formality", "animateness", "tense", etc. (not literally, but that is the geometric idea).
- At check-in (the start of training), every profile is filled with random numbers. By checkout (end of training), the profiles have been rewritten to reflect patterns learned from millions of sentences.
- Two guests that are often seen in the same contexts (cat, dog) end up with similar profiles. A guest from a very different context (car) ends up with a different profile.
Common misconceptions to tackle:
- "Embeddings are the word's meaning" — No: they are learned numeric patterns that help a specific model on a specific task. "Meaning" is a human concept; embeddings approximate certain aspects of it.
- "I can swap embedding tables between models" — No: different models have different vocabularies, different dimensions, and different geometric structures. They are not interchangeable.
- "Bigger embedding dimension = better meaning" — Not necessarily. d=64 may be enough for a small task; d=4096 is needed for GPT-4. The right size depends on model scale and task complexity.
- "Token IDs and embeddings are the same thing" — No: a token ID is an integer address. An embedding is the dense float vector stored at that address. One is a key; the other is the value.
Build + SummaryCement your understanding
🔨 Mini-Projects
1 · Build an embedding table from scratch
Create a 10-token vocabulary dictionary and a corresponding 10 × 4 embedding matrix as a Python list of lists. Write a function that takes a word, returns its token ID, and returns the corresponding embedding row. Verify it returns the correct row for each token.
2 · Inspect a real embedding table
Load bert-base-uncased with HuggingFace Transformers. Access model.embeddings.word_embeddings.weight. Print the shape. Look up the embeddings for "cat" and "dog" (get IDs from the tokenizer). Compute the cosine similarity between them.
3 · Compare static embedding geometry
Using a pre-trained model, retrieve embeddings for 10 words (5 animals, 5 vehicles). Compute cosine similarity between all pairs. Confirm that within-group similarities are higher than cross-group similarities. Visualise with a heatmap if possible.
Summary
Token ID
Integer address. Arbitrary. No magnitude meaning. Used only as a lookup key into the embedding table.
Embedding
Dense float vector of shape $(d,)$. Learned via gradient descent. Geometrically encodes training patterns.
Table shape
$E \in \mathbb{R}^{V \times d}$. One row per vocabulary token. V × d ≈ 38M params for GPT-2 small.
