Embeddings: meaning as geometry
How does a machine turn meaning into distances?
Lesson complete
If you like:
A customer writes “I want my money back,” and the right article talks about a “refund.” They share not one word. How can a machine see that they mean the same thing?
No voice: the lesson advances on its own with subtitles.
The voice for this lesson is being recorded: for now it advances on its own with subtitles.
Review modeComment on this stepI finished the lesson
What you will achieve
- Explain why a dense, learned vector represents meaning better than one slot per word (one-hot).
- Compute the cosine similarity between two vectors and interpret neighbors, 2D maps, and meaning arithmetic, with their limits.
- Recognize how the biases in text travel into vector space, and how to evaluate a semantic search with your own cases.
Key ideas
- An embedding is a dense, learned vector: a row of a table tuned by data, instead of a fixed slot per word.
- What shows up in similar contexts ends up with similar vectors: meaning becomes angle and distance.
- Cosine similarity compares directions, not lengths. A 2D map is a projection and loses information: use it to explore, not to measure.
- Meaning arithmetic is real but fragile: the input words must be excluded, and it works best on clean relations, such as country and capital.
- Vectors inherit the biases of the text. Semantic search rescues paraphrases, and its quality is measured with your own cases.
What many people believe
Common belief “King − man + woman = queen” proves that the model understands what royalty and gender are.
What is true It is a real geometric regularity, but a fragile one: it only comes out when the input words are excluded, it fails on many relations, and the same vectors carry the biases of the text. Measuring is not understanding.
Check yourself
Four questions. No grade, no account: they just show whether the idea stuck.
Under the hoodFor those who want the math and the code. You do not need it to follow the course.
An embedding is a row of a matrix
Let be the vocabulary size and the dimension of the vectors. The table is a matrix . The word with index is the one-hot vector (a one at position , zeros elsewhere) and its embedding is
Multiplying by a one-hot equals picking a row: it is a linear layer with no activation (lesson 7) whose weights are learned. With and that is numbers. In practice nothing is multiplied: the row is looked up. The same mechanism opens language models: in the smallest GPT-2 the table is million parameters (lessons 20 and 22).
Cosine similarity
If both vectors have length 1, and : ranking by cosine and ranking by Euclidean distance gives the same order. Example: and give , an angle of about . With (“dog” and “cat”) the angle is .
Where do the numbers come from?
Skip-gram (Mikolov et al., 2013) maximizes the average probability of the neighbors of each word , with a window of size :
Each word has an input vector (its embedding) and an output vector . The denominator runs over the whole vocabulary, which is why the paper proposes approximations such as negative sampling. GloVe (Pennington et al., 2014) instead fits
where counts how often appears near in the corpus, trained with AdaGrad. Two roads, one idea: words that share contexts end up with similar vectors.
The arithmetic, step by step
The question “ is to as is to ...” is answered with
With length-1 vectors, does not depend on , so this equals maximizing . The exclusion is not a detail: Linzen (2016) measured that, without it, the closest word was in 93% of cases and in 5%. In this lesson, with GloVe’s 100 numbers and choosing among its 400,000 words:
| Questions | With exclusion | Without exclusion | The closest was one of the 3 inputs |
|---|---|---|---|
| Capital–country (342) | 80.1% (274) | 68.1% | 19.3% |
| Gender (90) | 85.6% (77) | 55.6% | 41.1% |
I picked the pairs, and they are clean relations; the Mikolov et al. set (19,544 questions, 14 types, counting only the exact word, not synonyms) is harder: their best model reached 65.6%. With only the lesson’s 880 words the exam is far easier (94.4% and 85.6%): there are fewer candidates to get wrong. Linzen adds that the method mixes the consistency of the offset with neighborhood structure: it does not measure “relations” alone.
How the bias is measured in the lesson
With = {woman, girl, mother, wife, sister, daughter} and = {man, boy, father, husband, brother, son}, the score of a word is
Positive means closer to the female words. Sets are used rather than a pair because “man” has several senses. It is a simplified version of the association tests of Caliskan et al. (2017). Result over the 52 professions in the vocabulary: from (“boss”) to (“receptionist”); 26 objects with no gender (table, tree, river…) fall between and . The Spearman correlation with the “she” − “he” score in the full GloVe is 0.91. The score mixes gender with topic (in the text, the female words show up more next to “dress” or “soap”): it shows the slope, it is not a verdict about any person. If each vector has its component along (normalized) subtracted, the score on that axis is 0 by construction; even so, guessing whether each profession was above or below the median of the original score, with the nearest cosine centroid and leaving one out at a time, gets 41 of 52 right before and 35 of 52 after (chance: 26). It is a minimal experiment, with few words, in the spirit of Gonen and Goldberg (2019), who showed that methods for “debiasing” mostly hide the bias rather than remove it.
Semantic search
The average of a text with words is ; documents are ranked by . Comparing against documents costs per query, and with millions of them approximate indexes are used. Sentence vectors (Reimers and Gurevych, 2019) are computed once per document: finding the most similar pair among 10,000 sentences with BERT takes about 50 million inferences (about 65 hours); with sentence vectors, about 5 seconds. The third column of the scene uses paraphrase-multilingual-MiniLM-L12-v2 (Apache-2.0, 384 dimensions, more than 50 languages; Reimers and Gurevych, 2020), with the mean of the output vectors and cosine. Its scores were computed offline for the 36 test questions.
With 36 questions, 21 hits (the vector average on the English questions) are 58.3% with a 95% Wilson interval of 42% to 73%: a margin of about ±15 points. That is why lesson 34 insists on sample size.
In code
With toy vectors (invented numbers) the whole mechanism is visible:
import numpy as np
# Toy embedding table: one row per word, 3 numbers each (invented; a real model uses hundreds).
words = ["king", "queen", "man", "woman", "bread"]
E = np.array([
[4.0, 3.0, 1.0], # king
[4.0, 0.5, -2.0], # queen
[4.0, 0.0, 1.0], # man
[4.0, 0.0, -1.0], # woman
[0.0, 0.5, 3.0], # bread
])
E = E / np.linalg.norm(E, axis=1, keepdims=True) # length 1: the dot product is the cosine
row = {w: i for i, w in enumerate(words)}
def cosine(a, b):
return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
def closest(v, exclude=()):
pairs = [(w, round(cosine(v, E[i]), 2)) for w, i in row.items() if w not in exclude]
return sorted(pairs, key=lambda p: -p[1])[:3]
print(round(cosine(E[row["king"]], E[row["queen"]]), 2)) # king and queen
v = E[row["king"]] - E[row["man"]] + E[row["woman"]] # king - man + woman
print(closest(v)) # without excluding
print(closest(v, exclude=["king", "man", "woman"])) # excluding the three inputs
# 0.68
# [('king', 0.89), ('queen', 0.87), ('woman', 0.81)]
# [('queen', 0.87), ('bread', -0.18)]
And with the real GloVe vectors (the file glove.6B.100d.txt comes from the Stanford page, see the sources; reading it takes a few seconds):
import numpy as np
words, rows = [], []
with open("glove.6B.100d.txt", encoding="utf8") as f:
for line in f:
w, _, rest = line.partition(" ")
words.append(w)
rows.append(np.asarray(rest.split(), dtype=np.float32))
E = np.stack(rows)
E /= np.linalg.norm(E, axis=1, keepdims=True) # length 1: the dot product is the cosine
idx = {w: i for i, w in enumerate(words)}
def closest(v, k=5, exclude=()):
s = E @ (v / np.linalg.norm(v))
for w in exclude:
s[idx[w]] = -1
top = np.argsort(-s)[:k]
return [(words[i], round(float(s[i]), 2)) for i in top]
print(closest(E[idx["dog"]], 5, exclude=["dog"]))
v = E[idx["king"]] - E[idx["man"]] + E[idx["woman"]]
print(closest(v, 3))
print(closest(v, 3, exclude=["king", "man", "woman"]))
# [('cat', 0.88), ('dogs', 0.83), ('pet', 0.74), ('puppy', 0.72), ('horse', 0.71)]
# [('king', 0.84), ('queen', 0.77), ('monarch', 0.68)]
# [('queen', 0.77), ('monarch', 0.68), ('throne', 0.68)]
Where this lesson’s data come from
Vectors: GloVe 6B with 100 dimensions (Wikipedia 2014 and Gigaword 5, 6 billion words, 400,000 vocabulary, English only), published by Stanford under the Public Domain Dedication and License v1.0, which allows redistribution. They are normalized to length 1 and stored in 8 bits (maximum cosine error 0.0095). The map is t-SNE (van der Maaten and Hinton, 2008) with perplexity 20, cosine metric, and seed 0: Wattenberg et al. (2016) warn that in a t-SNE the size of clusters and the distance between them may mean nothing. The 10 support articles and the 36 test questions were written by the lesson’s author: they are illustrative. Everything can be regenerated with the scripts in the lesson folder (build-vectors.py, eval-search.py, eval-analogies.py, measure-data.py).
What comes next
The vectors in this lesson are static: one word, one vector. Attention (lesson 21) and the transformer (lesson 22) produce a different vector for each word depending on the sentence. Lesson 15 asks whether, besides representing what exists, a network can generate something new; lesson 18 puts image and text vectors in one shared space, and lesson 31 uses semantic search to give a model knowledge of its own.
Decision lens
What this idea means if your job is to decide, not to code.
- Semantic search and vector databases: every document becomes a vector once, and every question on the spot. Ask which embedding model is used, how many dimensions, in which languages, and under what license: if the model changes, the whole index must be recomputed.
- Measure quality with your own cases: a few dozen real questions, each with its correct document, and count how often it comes first or among the top five. With thirty-six cases the margin is about fifteen points; with more, the comparison sharpens.
- Embeddings inherit the biases of the text. If they rank people (résumés, candidates, customers), ask how bias was measured on data from that use; “we fixed it” is not enough, because removing one direction usually hides the bias rather than removing it.
- Warning signs: a 2D map presented as proof of quality, a demo with hand-picked questions, the phrase “it understands meaning” with no measured results, or an English model applied to Spanish texts without checking it.
Terms in this lesson
- Embedding A vector of numbers, learned from data, that represents something (a word, a sentence, an image) so that similar things end up close. Each word has a row in an embedding table.
- Cosine similarity The cosine of the angle between two vectors: 1 if they point the same way, 0 if they are perpendicular, −1 if they oppose. It ignores length and measures direction only.
- Vector space A space whose points are vectors. In an embedding space, the distance or angle between two points measures how alike their meanings are.
- Semantic search Search by meaning: the query and the documents are turned into vectors and the closest documents are returned, even if they share no words.
- Vector An ordered list of numbers. In machine learning, each example reaches the model as a vector.
- Feature One measurement of an example expressed as a number: the number of links in an email, the brightness of a pixel. The features of an example make up its vector.
- Layer A group of neurons that receive the same inputs and compute at the same time. A network is a chain of layers: input, one or more hidden ones, and output.
- Weight (w) In a linear model, the number that multiplies the input: the slope of the line. It tells how much the prediction rises for each unit the input grows.
- Parameter Each of the numbers a model adjusts while training and in which it stores what it learned.
- Gradient descent A method that adjusts the weights step by step, always against the slope of the error (the gradient), until it reaches a bottom.
- Training data Examples, each with its correct answer, from which a model adjusts its parameters.
Full transcript
Sources
- Mikolov, T., Chen, K., Corrado, G., Dean, J. (2013). Efficient Estimation of Word Representations in Vector Space
- Mikolov, T., Sutskever, I., Chen, K., Corrado, G., Dean, J. (2013). Distributed Representations of Words and Phrases and their Compositionality
- Mikolov, T., Yih, W., Zweig, G. (2013). Linguistic Regularities in Continuous Space Word Representations
- Pennington, J., Socher, R., Manning, C. D. (2014). GloVe: Global Vectors for Word Representation (artículo y datos, licencia PDDL v1.0)
- van der Maaten, L., Hinton, G. (2008). Visualizing Data using t-SNE
- Wattenberg, M., Viégas, F., Johnson, I. (2016). How to Use t-SNE Effectively
- Linzen, T. (2016). Issues in evaluating semantic spaces using word analogies
- Bolukbasi, T., Chang, K.-W., Zou, J., Saligrama, V., Kalai, A. (2016). Man is to Computer Programmer as Woman is to Homemaker? Debiasing Word Embeddings
- Caliskan, A., Bryson, J. J., Narayanan, A. (2017). Semantics derived automatically from language corpora contain human-like biases
- Gonen, H., Goldberg, Y. (2019). Lipstick on a Pig: Debiasing Methods Cover up Systematic Gender Biases in Word Embeddings But do not Remove Them
- Reimers, N., Gurevych, I. (2019). Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks
- Reimers, N., Gurevych, I. (2020). Making Monolingual Sentence Embeddings Multilingual using Knowledge Distillation
CommentsThis lesson’s public conversation: questions, facts to check, ideas.
Comments live in GitHub Discussions, in the course’s public repository; writing one requires a GitHub account. They load from giscus.app when you open this section. The course reviewers read them, and if a change is accepted, it is applied in both languages. Open the thread on GitHub