Expert: deep learning and AI · NLP, embeddings and large language models · topic 50 of 62 · 35 min
Embeddings and cosine similarity
Explanation
Meaning as a position
With TF-IDF, "refund" and "money back" share nothing. An embedding model is trained so that texts with similar meaning land close together in a space with hundreds of dimensions. A query like "money not returned" can then find documents about refunds even if they use different words. This is called semantic search: search by meaning, not exact words.
Where embeddings come from
Word2vec (2013) learned word vectors by predicting a word from its neighbours. It famously captured relationships like king − man + woman ≈ queen, although such neat analogies work less often than the famous example suggests. Today, sentence-embedding models built on transformers produce one vector per sentence or paragraph, and many APIs and open models offer them. The same idea works for images, songs and products.
Measuring similarity: cosine
Cosine similarity = (a · b) ÷ (|a| × |b|), where a · b is the dot product (multiply matching numbers and add) and |a| is the length (square root of the sum of squares). It measures the angle between the vectors: 1 means same direction (very similar), 0 means unrelated (at right angles), −1 means opposite. It ignores length, so a long and a short document about the same topic can still score high.
import math
def cosine(a, b):
dot = sum(x * y for x, y in zip(a, b))
return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))
print(round(cosine([1, 2, 3], [2, 4, 6]), 4), round(cosine([1, 1], [1, 0]), 4))Semantic search in three steps
- Embed every document once and store the vectors.
- When a query arrives, embed it with the same model.
- Compute cosine similarity with every stored vector and return the top matches.
With millions of documents, comparing with every vector is slow, so vector indexes and databases do approximate nearest-neighbour search very fast. Examples include FAISS (a library), pgvector (an extension for PostgreSQL) and dedicated vector databases. Module 11 builds RAG on this.
Common mistakes
- Comparing vectors made by different embedding models. Their spaces are unrelated; always use one model for both documents and queries.
- Dividing by zero for an all-zero vector. Guard it and return 0.
- Assuming high similarity means "correct answer". Similar is not the same as true; check results.
- Embedding very long documents as one vector, which blurs the meaning. Split them into chunks first (module 11).
Need help?
Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.
Try:
Watch the lesson
Embeddings and cosine similarity · 1/6
An embedding is a list of numbers that captures meaning. Similar meanings get similar vectors.
Prefer a video by a teacher? Find free videos on “word embeddings cosine similarity semantic search explained” on YouTube ↗
In real life: Finding similar support answers
An insurance company embeds its 3,000 help-centre answers. When a customer types "my claim money has not reached my account", the system embeds the question, finds the most similar answers by cosine similarity, and shows "How long does claim settlement take?" even though the words differ. Agents get the same suggestions inside their tools, which cuts reply times.
import math
def cosine(a, b):
dot = sum(x * y for x, y in zip(a, b))
return dot / (math.sqrt(sum(x * x for x in a)) * math.sqrt(sum(y * y for y in b)))
answers = {"claim settlement time": [0.9, 0.1, 0.3], "change nominee": [0.1, 0.8, 0.2]}
query = [0.8, 0.2, 0.25] # toy 3-number embeddings; real ones have hundreds
print(max(answers, key=lambda k: cosine(query, answers[k])))Practice (0/2 done)
Write cosine_similarity(a, b) that returns (a · b) / (|a| × |b|) rounded to 4 decimal places. If either vector has length 0 (all zeros), return 0.0.
Write most_similar(query, docs) where docs is a dict mapping a title to its embedding vector. Return the title with the highest cosine similarity to query. On a tie, return the title that comes first in the dict. Return None if docs is empty.
Quick quiz
Read more (free)
Related help
Before this, learn
This topic builds on these. If something here feels new, open them first.
Related topics
- How large language models workNLP, embeddings and large language models · same module
- Working with text: tokens and cleaningNLP, embeddings and large language models · same module
- Retrieval-augmented generation (RAG)Building with generative AI, and MLOps
- Semantic HTMLFrontend Web Development · Forms, semantic HTML and accessibility
- Arrays, std::array and a first look at std::vectorC++ Programming (modern C++ and DSA) · References, pointers, arrays and strings
- std::vector in depthC++ Programming (modern C++ and DSA) · The Standard Template Library (STL)
Questions people ask about this
Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.
What is an embedding?
Answer: A vector of numbers that represents meaning, so similar items are close
Embeddings place similar meanings near each other.
Cosine similarity of two vectors pointing in exactly the same direction is…
Answer: 1
Cosine ignores length; same direction gives 1.
Why can semantic search find "refund" documents for the query "money back"?
Answer: Their embeddings are close in meaning
The embedding model learned that they mean similar things.
You embed documents with model A and queries with model B. What happens?
Answer: Meaningless comparisons, because the vector spaces are different
Use one model for both sides.
What is pgvector?
Answer: A PostgreSQL extension for storing and searching vectors
It adds vector columns and similarity search to PostgreSQL.
Users search for "Section 80C limit". Pure vector search sometimes misses exact codes. What helps?Related
Answer: Hybrid search combining keywords with vectors
Keyword search is good at exact terms and numbers.
What does a bag-of-words vector ignore?Related
Answer: The order of the words
Only counts remain; order is lost.
A product review that makes sense on its own fits best in...Related
Answer: <article>
An article is self-contained content that could be shared on its own.
From Semantic HTML
How does k-NN classify a new point?Related
Answer: It takes a vote among the k closest training points
The k nearest neighbours vote.
From k-nearest neighbours
Pass the quiz (60% or more) or mark this topic as done when you are ready.
Your progress is saved on this device only.
Next steps
- 2 more topics in “NLP, embeddings and large language models” before its exam: How large language models work, Prompting well.
- Module 10 exam: NLP, embeddings and large language models · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
- Then the next module, Building with generative AI, and MLOps. 62 topics left in the course before the final exam.