How Embeddings Are Learned
Understand the mechanism that turns random vectors into meaningful geometry. The distributional hypothesis, gradient descent on the embedding table, and why tokens used in similar contexts end up nearby in vector space.
Learning Embeddings: Pulling Nearby Concepts Together
The scholar begins life with random static in their memory drawers. But as they read trillions of sentences across the library, the Distributional Hypothesis ("You shall know a word by the company it keeps" — J.R. Firth) guides them. Every time "cat" and "dog" occur surrounded by "pet", "fur", and "vets", backpropagation applies tiny gravitational tugs pulling their drawer vector knobs closer together in vector space.
IntroductionFrom random noise to meaningful structure
When a model is initialised, every token in the vocabulary gets assigned a random vector — just noise. A randomly initialised vector for cat might be [0.03, -0.11, 0.07, ...], while dog gets [-0.08, 0.14, -0.02, ...]. These two vectors are not especially close. They have no meaning yet.
By the end of training on a large corpus, the same vectors become neighbours in a high-dimensional space. No one hand-crafted these numbers. The model adjusted them, one gradient step at a time, to reduce prediction error. The geometry is a byproduct of the training objective.
At initialisation
Vectors are random. cat and dog are as similar as cat and car. The embedding table is just uninitialised parameters.
After training
Vectors reflect usage patterns. cat and dog cluster together. Paris relates to France the way Berlin relates to Germany.
WhyWhy does the model need to learn the embedding table?
Because the right geometry depends on the task, the language, and the domain. There is no universal "correct" vector for bank — the right representation depends on whether the corpus is financial news, river ecology papers, or general English conversation. A pre-fixed table could not capture these specific patterns.
Learning the embedding table means the model discovers the geometry that best serves the training objective. Changing the task or data changes what gets learned.
Task-shaped
Fine-tune on code → code-specific geometry. function clusters near return and class, not near "mathematical function" or "social function".
Language-shaped
Multilingual corpus → cross-lingual alignment. The vector for cat in English may be close to chat in French after multilingual pretraining.
Domain-shaped
Medical text → clinical relationships. aspirin clusters near drug names and dosage terms rather than near "aspiration" or "spiral".
Data-shaped
Biased data → biased geometry. If certain words appear together due to societal bias in the corpus, the embeddings will reflect that bias.
IntuitionThe Distributional Hypothesis
"A word is known by the company it keeps" — J.R. Firth, 1957. This is the distributional hypothesis, and it is the conceptual foundation of learned embeddings.
If cat and dog appear repeatedly in similar sentence contexts — "The [word] sat on the mat", "The [word] slept on the sofa", "She gave the [word] some food" — then during training, the gradients for both tokens will be nudged in similar directions. Over many steps, their vectors converge.
Contexts containing "cat": "The cat sat on the mat." "The cat slept on the sofa." "She gave the cat some food." Contexts containing "dog": "The dog sat on the mat." "The dog slept on the sofa." "She gave the dog some food." → Similar contexts → similar gradient direction → similar vectors
car co-occurs with drive, engine, road. cat co-occurs with fur, meow, pet. Their gradient updates push them apart, not together.TheoryThe embedding table as a learnable parameter matrix
The embedding table is a matrix $E \in \mathbb{R}^{V \times d}$ where $V$ is vocabulary size and $d$ is embedding dimensionality. Each row $E[t]$ is the vector for token $t$. This matrix is a learnable parameter — it is updated by gradient descent exactly like the weights of any other layer.
Token ID vs vector: which is which?
Think of the embedding table as a database table. To keep it small, each vector below has just 4 numbers:
| Token ID (token) | Dim 1 | Dim 2 | Dim 3 | Dim 4 |
|---|---|---|---|---|
| 0 (the) | 0.21 | −0.14 | 0.72 | 0.08 |
| 1 (cat) | 0.80 | −0.30 | 0.40 | 0.15 |
| 2 (dog) | 0.75 | −0.25 | 0.45 | 0.12 |
Illustrative values only. Real embedding values are learned during model training.
Token ID 1 → identifies the row for "cat" Row 1 = [ 0.80, −0.30, 0.40, 0.15 ] ← the vector for "cat"
A token ID does not contain vector numbers. ID 1 is not the vector [0.80, −0.30, 0.40, 0.15]; it simply tells the model which vector to retrieve.
Where do the vector numbers come from?
- Initially, the values are typically set by a numerical initialization scheme.
- During training, the model adjusts them through optimization and backpropagation (the update rule above).
- Over time, the values become useful for the model's language-processing task.
In a real LLM each vector may contain hundreds or thousands of numbers. Token ID = which row? Vector = the learned numbers stored in that row. What “4 numbers” means is explained in Vector Dimensions.
372 did not appear in the batch, its row receives no gradient and is not updated.How It WorksThe training loop step-by-step
Each training iteration follows the same loop. The embedding table is updated as a side-effect of training the model on its objective (next-token prediction, masked language modelling, or another task).
- Sample a batch of text from the corpus.
- Tokenize → convert to token IDs.
- Look up embedding rows for those IDs: $x_i = E[t_i]$ for each token $t_i$ in the batch.
- Pass embeddings through the model layers (attention, feed-forward, etc.).
- Compute the training loss $\mathcal{L}$ (e.g. cross-entropy against the target tokens).
- Backpropagate: compute $\nabla_{E[t_i]} \mathcal{L}$ for each token $t_i$ seen in the batch.
- Optimizer updates those embedding rows: $E[t_i] \leftarrow E[t_i] - \eta \cdot \nabla_{E[t_i]} \mathcal{L}$.
- Repeat for millions of batches.
MathematicsSparse gradient updates in detail
Consider a batch containing tokens $\{t_1, t_2, \ldots, t_B\}$ (with possible repetitions). The full gradient matrix $\nabla_E \mathcal{L}$ has the same shape as $E$ — but most rows are exactly zero.
Frequent token: "the"
Appears in nearly every sentence. Updated hundreds of thousands of times. Its vector is well-optimised to capture the distributional statistics of a common article.
Rare token: "osmium"
Appears infrequently. Updated rarely. Its vector may not converge well — the model has seen too few examples to shape its geometry reliably.
Worked ExampleTwo-token toy training scenario
Consider a minimal vocabulary of two tokens: cat (ID 0) and dog (ID 1). The embedding table starts as:
Training repeatedly sees the sentences "the cat sat on the mat" and "the dog sat on the mat". For the target word sat, both cat and dog are the preceding context. The gradient updates for both rows point in directions that better predict sat from the context.
VisualizeTraining loop as a flowchart
Each loop through the training data performs one gradient update. Over millions of iterations, the embedding table is gradually shaped by the training signal.
Each loop iteration slightly adjusts the vectors for tokens seen in that batch. After millions of iterations the geometry reflects distributional patterns in the corpus.
Early training
Vectors are nearly random. Similar words are not meaningfully closer than dissimilar ones. The model predicts poorly.
Late training
Vectors have drifted to positions that minimise loss. Semantic and syntactic clusters have emerged. Analogical relationships hold.
CodeManual gradient descent on a toy embedding table
The code below implements one step of embedding learning from scratch — no PyTorch, just NumPy arithmetic. It shows the gradient computation, sparse update, and how two tokens in similar contexts converge.
import numpy as np
# ── Toy setup ─────────────────────────────────────────────────────────────
# Vocabulary: {cat: 0, dog: 1, sat: 2}
# Task: given context token, predict target token (simplified skip-gram)
VOCAB_SIZE = 3 # cat, dog, sat
EMBED_DIM = 2 # 2D for easy visualisation
LR = 0.1
# Initialise embedding table randomly
rng = np.random.default_rng(42)
E = rng.uniform(-0.5, 0.5, (VOCAB_SIZE, EMBED_DIM))
# ── Simplified forward pass ────────────────────────────────────────────────
# Predict target from context via dot product + softmax
def forward(E, context_id, target_id):
"""Return loss and probability of target given context."""
context_vec = E[context_id] # shape: (d,)
logits = E @ context_vec # shape: (V,) — dot with all rows
logits -= logits.max() # numerical stability
probs = np.exp(logits) / np.exp(logits).sum()
loss = -np.log(probs[target_id] + 1e-9)
return loss, probs
# ── Training loop ──────────────────────────────────────────────────────────
# Training data: (context, target) pairs
# "cat sat" → (cat→sat) and "dog sat" → (dog→sat)
data = [(0, 2), (1, 2)] * 500 # 1000 pairs, same pattern for both
for step, (ctx, tgt) in enumerate(data):
loss, probs = forward(E, ctx, tgt)
# ── Gradient computation ──────────────────────────────────────────────
# d_loss / d_logits = probs - one_hot(target)
d_logits = probs.copy()
d_logits[tgt] -= 1.0 # gradient of cross-entropy + softmax
# d_loss / d_E[context] = E.T @ d_logits (from E @ context_vec = logits)
d_E_ctx = E.T @ d_logits # shape: (d,)
# ── Sparse update: only context row changes ───────────────────────────
E[ctx] -= LR * d_E_ctx
if step % 200 == 0:
sim = np.dot(E[0], E[1]) / (np.linalg.norm(E[0]) * np.linalg.norm(E[1]))
print(f"step {step:4d} loss={loss:.3f} cos(cat,dog)={sim:.3f}")
print("\nFinal cosine similarity between cat and dog:", end=" ")
sim = np.dot(E[0], E[1]) / (np.linalg.norm(E[0]) * np.linalg.norm(E[1]))
print(f"{sim:.4f} (should be close to 1.0 — same contexts)")
What this shows
- Gradient flows only through the context row (sparse update)
catanddogconverge because they share the same training signal- No explicit meaning is encoded — only prediction error
What PyTorch adds
- Autograd — no manual gradient formulas
- Batching and efficient sparse optimisers (SparseAdam)
nn.Embedding— same concept, GPU-accelerated
Hands-OnInspect embeddings before and after fine-tuning
🔬 Experiment: Embedding geometry inspection
Use HuggingFace to inspect how embeddings cluster before and after fine-tuning, and verify that cosine similarity tracks semantic proximity.
CompareHow different training setups shape the embedding table
The geometry of learned embeddings depends heavily on the training objective, data, and whether the table is frozen or fine-tuned downstream.
| Training mode | Example | Objective | When to freeze vs fine-tune |
|---|---|---|---|
| Explicit context window | word2vec skip-gram / CBOW | Predict context words from target (or vice versa) using a small window | Often frozen downstream — task-agnostic features |
| Implicit (full model) | BERT masked language model | Embeddings updated as part of full model training via MLM / NSP | Fine-tune all layers including embedding for domain adaptation |
| Fine-tuning | BERT fine-tuned on IMDB | Start from pretrained geometry, adapt embedding rows to task-specific signal | Fine-tune when domain differs significantly from pretraining corpus |
| Frozen embeddings | GPT-2 with frozen embedding layer | Keep pretrained embedding rows fixed; train only upper layers | Freeze when data is small — avoids overfitting embedding rows |
ApplyWhere learned embeddings appear in real systems
cos(cat, dog): -0.120
• Positive: (cat, dog), (cat, pet)
• Negative: (cat, quantum), (dog, matrix)
🔍 Behind-the-Scenes: Skip-Gram with Negative Sampling Loss
Mikolov et al.'s SGNS objective function:
- Positive Pair Pull: Maximizes sigmoid probability $\sigma(\vec{v}_w \cdot \vec{v}_c) \to 1$ for real co-occurring words.
- Negative Sample Push: Minimizes probability $\sigma(\vec{v}_w \cdot \vec{v}_{w_i}) \to 0$ for $k$ randomly selected noise words.
- Result: Self-organizing semantic clusters without labeled supervision!
LLMs (GPT, LLaMA, Mistral)
The embedding table is updated during pretraining as part of the full model. During fine-tuning, it may be frozen or updated depending on the task and dataset size.
Semantic search models
Models like Sentence-BERT are trained specifically to push similar sentence embeddings together (contrastive loss). The embedding geometry directly serves retrieval quality.
Domain adaptation
Continued pretraining on medical, legal, or code corpora reshapes the embedding geometry so domain terms cluster appropriately — improving downstream task accuracy.
Word analogies (classic)
The famous word2vec analogies (king − man + woman ≈ queen) emerge from distributional training. No analogy objective was used — the geometry self-organises from co-occurrence.
LimitationsWhat learning cannot fix
Training shapes the geometry, but it also encodes the flaws of the training data and process. Understanding these limitations is essential for responsible use.
- Bias amplification: Embeddings trained on biased corpora reflect those biases. Occupational stereotypes, racial associations, and gender biases found in text are baked into the vectors.
- Infrequent tokens: Rare tokens receive far fewer gradient updates. Their rows may not converge — their geometry can be nearly random relative to frequent tokens.
- Catastrophic forgetting: Fine-tuning on a new domain can shift embedding rows away from their pretrained geometry, degrading performance on the original domain.
- Non-interpretable dimensions: There is no clean correspondence between individual dimensions and human-readable concepts. The geometry emerges from the training signal, not from human design.
- Static embeddings are context-free: A single trained row for "bank" cannot capture both "river bank" and "financial bank" — the same vector is used regardless of context.
Common misconception
"A word's embedding is its true meaning, learned once and correct forever."
Better model
"A word's embedding is a statistical fingerprint of its usage in a specific corpus under a specific training objective. Different corpora and tasks produce different embeddings for the same word."
Feynman ChallengeCan you explain it simply?
Imagine explaining learned embeddings to a curious friend using the "detective without a dictionary" metaphor:
- The model is a detective who cannot look up word meanings in a dictionary — it only has the text.
- It notices: "cat" and "dog" keep showing up in the same kinds of sentences. Must be related.
- It adjusts its mental model of each word (its vector) to make future predictions less wrong.
- After millions of cases, the detective has a highly calibrated intuition — not because it was told meanings, but because it observed patterns.
- The "meaning" is the pattern of co-occurrence, captured as a direction in high-dimensional space.
Common misconceptions to tackle:
- "Embeddings are programmed with word meanings" — No: they start random and are adjusted by gradient descent to reduce prediction error. Meaning is never explicitly encoded.
- "Training makes all similar words neighbours" — No: "similarity" in embedding space means distributional similarity (similar contexts), not conceptual or semantic similarity in every sense. Antonyms can be neighbours.
- "A token's embedding is stable across all models" — No: the same word has different embeddings in BERT vs GPT-2 vs LLaMA because the training objectives, data, and architectures differ.
- "You can look at an embedding vector and read its meaning" — No: individual dimensions are not interpretable. The meaning lives in the geometric relationships between vectors.
- "Random init means training always produces the same geometry" — No: training is stochastic. Different random seeds, batch orderings, and hyperparameters produce different final geometries, though they may encode similar information.
Build + SummaryCement your understanding
🔨 Mini-Projects
1 · Embedding inspector
Load bert-base-uncased. Compute cosine similarity for 10 word pairs: (king, queen), (cat, dog), (happy, sad), (Paris, France), (run, walk). Plot the similarities as a bar chart. Explain why antonyms may cluster.
2 · Fine-tuning effect
Fine-tune a tiny BERT on a domain corpus (e.g. IMDB movie reviews). Compare cosine similarities for domain-specific terms (actor, director, sequel) before and after fine-tuning. Measure whether domain terms cluster more tightly post-fine-tuning.
3 · Gradient tracer
Implement the 3-token toy training loop from Phase 09. Log which embedding rows are updated per batch. Run 500 steps and observe: (a) sparse update pattern, (b) convergence of cat/dog cosine similarity, (c) effect of learning rate on convergence speed.
Summary
Random init
All embedding rows start as uninformative random vectors. No meaning is hand-coded.
Gradient updates
Backprop computes $\nabla_{E[t]} \mathcal{L}$ for tokens seen in each batch. The optimizer adjusts those rows. All other rows are unchanged that step.
Distributional hypothesis
Similar contexts → similar gradient corrections → similar vectors. The geometry emerges from co-occurrence patterns, not explicit semantic labelling.
Task-shaped geometry
Different tasks and corpora produce different embedding geometries. Fine-tuning shifts the geometry toward the new domain or task objective.
