Skip to content

Expert: deep learning and AI · NLP, embeddings and large language models · topic 50 of 62 · 35 min

Embeddings and cosine similarity

Explanation

An embedding is a list of numbers (a vector) that represents the meaning of a word, sentence, image or product, so that similar things get similar vectors. Cosine similarity measures how closely two vectors point in the same direction, from −1 to 1. Embeddings power semantic search, recommendations and RAG.

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.

Think of it like this: Think of a map of a city. Restaurants serving similar food tend to cluster: a lane full of South Indian tiffin places, another of Mughlai kitchens. An embedding is a map of meaning with hundreds of directions instead of two, where similar ideas sit near each other.

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.

python
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))
Shows 1.0 0.7071: the first pair point the same way (one is just twice as long); the second pair are 45° apart.

Semantic search in three steps

  1. Embed every document once and store the vectors.
  2. When a query arrives, embed it with the same model.
  3. 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

Embedding = meaning as numbers

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.

python
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])))
Shows claim settlement time.

Practice (0/2 done)

Task 1 · Code · Python

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.

Task 2 · Code · Python

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

Question 1

1.What is an embedding?

Question 2

2.Cosine similarity of two vectors pointing in exactly the same direction is…

Question 3

3.Why can semantic search find "refund" documents for the query "money back"?

Question 4

4.You embed documents with model A and queries with model B. What happens?

Question 5

5.What is pgvector?

Read more (free)

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.

From Retrieval-augmented generation (RAG)

What does a bag-of-words vector ignore?Related

Answer: The order of the words

Only counts remain; order is lost.

From Bag of words, TF-IDF and text classification

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

  1. 2 more topics in “NLP, embeddings and large language models” before its exam: How large language models work, Prompting well.
  2. Module 10 exam: NLP, embeddings and large language models · 12 questions · 25 min, without help. 5 topics of this module still to finish first.
  3. Then the next module, Building with generative AI, and MLOps. 62 topics left in the course before the final exam.

← Previous: Bag of words, TF-IDF and text classification