Suppose a dictionary assigns “workshop” the number 12 and “seminar” the number 13. Does their closeness mean the computer knows they are related? What if the dictionary assigns “banana” the number 14?
Before you begin: Know what a neural network takes as input. No vector algebra is required.
Tokens and their IDs
Computers need a numerical representation of text. One step is to divide text into units called tokens and map each token to an ID. A token might be a word, part of a word, a punctuation mark, or another unit chosen by the tokenizer. We will examine tokenization more closely later.
A token ID acts like an entry number in a catalog. It identifies an item; arithmetic on IDs does not provide a meaningful measure of similarity. Renumbering the catalog should not change what the words mean.
An embedding adds a learned representation. It maps an item to a list of numbers, called a vector. Instead of looking at the distance between catalog numbers, a model works with the pattern across those coordinates.
Represent a document with two numbers
For a toy search engine, describe documents with two features: how much they discuss teaching and how much they discuss food. Give “workshop guide” the vector [3, 0], “class notes” [2, 0], and “lunch menu” [0, 3].
Those coordinates are designed by us. In a learned embedding, the coordinates usually do not have labels as tidy as “teaching” and “food.” Training adjusts them so that relationships useful for an objective can be expressed by their geometry.
Try the query vector [1, 0]. The first two documents point in the same direction as the query; the menu points elsewhere. Cosine similarity compares directions. It divides the dot product of two vectors by the product of their lengths. The dot product multiplies corresponding coordinates and adds the results.
For [1, 0] and [3, 0], the dot product is three and the lengths are one and three. Their cosine similarity is one. For [1, 0] and [0, 3], the dot product is zero, so similarity is zero. A zero vector has no direction, so cosine similarity needs a policy for that case.
Token IDs and meaning
An ID solves a storage problem: it tells you which entry to look up. It does not solve a meaning problem. Renumbering the dictionary should not suddenly make “refund” closer to “receipt.” An embedding is different because its coordinates are learned or deliberately constructed so that a comparison has a useful role in a task.
The little geometry experiment makes one part of that comparison visible. Turning the candidate changes its direction; stretching it changes its length. Cosine similarity keeps only the angle relationship. Real embeddings have many coordinates and their usefulness depends on training and evaluation, so the drawing is an intuition for an operation, not a map of universal word meanings.
refund = 0, reimbursement = 1, receipt = 2 are arbitrary identifiers.
Swap IDs 1 and 2 while leaving the words themselves unchanged.
The numerical gaps change. The meanings do not. ID distance is therefore the wrong comparison.
Similar wording can mean different things
“Registrations are refundable” and “Registrations are not refundable” share a topic and much of their wording. They may be close in an embedding space while giving opposite answers to a learner's question. A search score indicates a relationship under a particular model; it does not certify truth, permission, or logical agreement.
Likewise, a vector near another vector is not a stored definition. Embeddings depend on the training data, objective, and model. Two unrelated embedding models generally produce different coordinate systems. You should not compare a query vector from one model with document vectors from another just because they have the same number of coordinates.
How context changes an embedding
A simple embedding lookup gives a token the same starting vector wherever it appears. Later parts of a language model can update that representation using surrounding tokens. This creates a contextual representation. The token “bank” can contribute differently in a fishing story and a payment question.
This does not require a little dictionary definition to appear inside each coordinate. It means that the numerical state used by the model depends on the context. Keeping the distinction between initial lookup and later contextual processing will make attention easier to understand.
Calculate cosine similarity
This complete Python 3 program implements cosine similarity for the toy vectors. The explicit error checks prevent silent comparisons of different dimensions or zero vectors.
# Runnable: Python 3, standard library.
import math
def cosine(a, b):
if len(a) != len(b) or not a:
raise ValueError('Vectors need equal, nonzero dimensions')
lengths = math.sqrt(sum(x*x for x in a))
lengths *= math.sqrt(sum(x*x for x in b))
if lengths == 0:
raise ValueError('A zero vector has no direction')
return sum(x*y for x, y in zip(a, b)) / lengths
assert cosine([1, 0], [3, 0]) == 1
assert cosine([1, 0], [0, 3]) == 0
print(round(cosine([1, 0], [1, 1]), 3))
Before running it, decide whether the last score should be above zero and below one. Then replace [1, 1] with [10, 10].
Explain what stays the same
Both vectors point in the same direction, so both scores are about 0.707. Cosine similarity ignores a positive rescaling of a vector. Other similarity measures may behave differently. Choose the metric recommended for the embedding model and evaluate retrieval on actual questions.
Practice with feedback
Turn a vector without stretching it
The query is [1, 0]. The candidate is [length × cos(angle), length × sin(angle)]. Cosine divides the dot product by the lengths of both vectors.
Candidate vector: [0.707, 0.707]
At 90 degrees the dot product is zero. At 180 degrees it is negative. Stretch the candidate at a fixed angle: the raw dot product changes, but the cosine stays fixed.
What this experiment assumes. Two-dimensional geometry, not measured semantic similarity. A negative cosine is a direction relationship, not proof that two statements contradict each other. Notes and recorded results here last until you leave this page.
Compare cosine similarity against your own judgement
You give each word an ID: refund=0, reimbursement=1, receipt=2. IDs make words storable but say nothing about meaning: 0 and 1 are no closer than 0 and 2.
Build small vectors, measure similarity, and find where the number disagrees with meaning.
Check your understanding
Your task
Write cosine similarity, run it on three pairs, and find one pair where the number misleads you.
These notes stay on this page. Download them before leaving. Code in this field is not executed.
What to include
- cosine normalises by both vector lengths, so scaling a vector does not change the score
- Scores are printed in ranked order with the pair names
- You state the ranking you expected before running it
- You name one pair where a high score would still be a bad substitution
Compare with a worked answer
Here is one way to answer. Check how it uses the information in the task.
import numpy as np
vocab = {
'refund': np.array([0.9, 0.1, 0.2]),
'reimbursement': np.array([0.85, 0.15, 0.25]),
'receipt': np.array([0.6, 0.7, 0.1]),
'venue': np.array([0.1, 0.2, 0.95]),
}
def cosine(a, b):
return float(a @ b / (np.linalg.norm(a) * np.linalg.norm(b)))
pairs = [('refund', 'reimbursement'), ('refund', 'receipt'), ('refund', 'venue')]
scored = sorted(((cosine(vocab[x], vocab[y]), x, y) for x, y in pairs), reverse=True)
for s, x, y in scored:
print(f'{x:>14} ~ {y:<14} {s:.3f}')
# refund ~ reimbursement 0.998
# refund ~ receipt 0.879
# refund ~ venue 0.353
#
# The ranking matches what I expected. The score I would not trust is
# refund ~ receipt at 0.879. It is high enough to look like a match, but a
# person asking for a receipt does not want their money back. If I used a
# 0.85 threshold to auto-route messages, receipts would land in refunds.
When you are signed in, opening the challenge carries your edited working notes into its draft in this browser. The challenge has its own completion record. Practising here does not award points or mark it complete.
Next, we will ask how a model combines these representations across a sentence instead of interpreting each item alone.
Further reading
Google's embeddings module introduces representation learning. Sentence-BERT is a research example of learning sentence representations for similarity tasks.