Cosine Similarity
Learn how cosine similarity compares embedding vectors by looking at the angle between them. You will understand the formula, dot product, vector magnitude, Python implementation, ranking, edge cases, and how cosine similarity supports semantic search and RAG.
By the end of this lesson, you will be able to:
- Explain cosine similarity in simple terms.
- Understand the dot-product and magnitude parts of the formula.
- Explain why the angle between vectors matters.
- Calculate cosine similarity with Python and NumPy.
- Use cosine similarity to rank embedding candidates.
- Handle zero vectors and interpret scores carefully.
- Connect cosine similarity to semantic search and RAG.
What Is Cosine Similarity?
Cosine similarity is a metric used to compare two vectors. Instead of primarily asking how far apart the vectors are, it asks how closely their directions align.
The Core Formula
For two vectors A and B, cosine similarity divides their dot product by the product of their magnitudes.
Why the Angle Matters
Imagine vectors as arrows starting at the same origin. If two arrows point in nearly the same direction, the angle between them is small and cosine similarity is high.
Understanding the Dot Product
The dot product is one of the building blocks of cosine similarity. For two same-length vectors, multiply corresponding components and add the results.
Understanding Vector Magnitude
Magnitude is the length of a vector. For a vector with components xβ, xβ, β¦, xβ, its magnitude is the square root of the sum of squared components.
More magnitude
Its length is larger, but cosine similarity can still be high if its direction matches another vector.
Same direction
Scaling a vector changes its length without changing its direction.
Cosine Similarity vs Euclidean Distance
Both metrics compare vectors, but they answer different questions. Cosine similarity focuses on direction; Euclidean distance measures straight-line distance between points.
How aligned?
Useful when the orientation of embedding vectors matters more than their raw length.
How far apart?
Measures geometric distance directly and can be sensitive to vector magnitude.
Python: Calculate Cosine Similarity
Here is the basic NumPy implementation. It makes every part of the formula visible.
import numpy as np
def cosine_similarity(a, b):
dot_product = np.dot(a, b)
magnitude_a = np.linalg.norm(a)
magnitude_b = np.linalg.norm(b)
return dot_product / (magnitude_a * magnitude_b)
a = np.array([1, 2, 3])
b = np.array([2, 4, 6])
score = cosine_similarity(a, b)
print(f"Cosine similarity: {score:.3f}")Python: Compare Different Directions
Changing the direction changes the cosine score, even when the vectors have similar dimensions.
import numpy as np
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
vectors = {
"same direction": (np.array([1, 2]), np.array([2, 4])),
"perpendicular": (np.array([1, 0]), np.array([0, 1])),
"opposite": (np.array([1, 2]), np.array([-1, -2])),
}
for label, (a, b) in vectors.items():
score = cosine_similarity(a, b)
print(f"{label}: {score:.3f}")What Do Cosine Scores Mean?
For the standard cosine similarity formula, the mathematical range is -1 to 1. In many embedding applications, scores may cluster in a narrower positive range, so the raw number should not be interpreted with a universal rule.
Ranking Search Results with Cosine Similarity
Semantic search commonly calculates a query-to-document similarity score and sorts candidates from highest to lowest.
import numpy as np
def cosine_similarity(a, b):
return np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
query = np.array([0.8, 0.2, 0.1])
documents = {
"password reset": np.array([0.78, 0.24, 0.12]),
"account login": np.array([0.70, 0.30, 0.15]),
"weather forecast": np.array([0.05, 0.90, 0.20]),
}
results = []
for name, vector in documents.items():
score = cosine_similarity(query, vector)
results.append((name, score))
results.sort(key=lambda item: item[1], reverse=True)
for name, score in results:
print(f"{name}: {score:.3f}")The highest-scoring candidate becomes the first retrieval result. A production system may then apply metadata filters, reranking, business rules, or a relevance threshold.
Why Normalization Matters
Cosine similarity divides by both vector magnitudes, which makes the comparison less dependent on raw vector length. This is one reason it is useful for high-dimensional representations.
Zero Vectors: An Important Edge Case
A zero vector has no direction. Because its magnitude is zero, the cosine formula would divide by zero. Your implementation should therefore handle zero vectors explicitly.
import numpy as np
def cosine_similarity(a, b):
denominator = np.linalg.norm(a) * np.linalg.norm(b)
if denominator == 0:
return 0.0
return np.dot(a, b) / denominator
print(cosine_similarity(
np.array([0.0, 0.0]),
np.array([1.0, 2.0])
))Cosine Similarity in Semantic Search
A typical semantic search pipeline creates a vector for the user's query, compares it with stored document vectors, and retrieves the strongest matches.
Cosine Similarity in RAG
In RAG, cosine similarity can help identify which document chunks are closest to the query in embedding space before those chunks are passed to the language model.
Retrieval quality still depends on chunking, embedding model, metadata, indexing, query rewriting, reranking, and evaluation. Cosine similarity is one component of the retrieval process.
Common Mistakes
The denominator is what normalizes the dot product by vector lengths.
A score that works for one dataset may fail on another.
Always protect the denominator in custom implementations.
Vectors need to belong to a compatible embedding space.
Similarity ranks content; it does not verify facts.
Hybrid retrieval can be useful when names, IDs, codes, or exact terms matter.
When Should You Use Cosine Similarity?
Rank documents by embedding-direction similarity.
Compare a user question with known questions.
Find candidate chunks for an LLM context window.
Find records with similar semantic representations.
Compare user and content representations.
Use vector similarity as one signal when grouping content.
Build a Cosine Similarity Ranker
Create a small Python experiment that ranks FAQ embeddings against a user query.
- Create five sample FAQ vectors.
- Create one query vector.
- Implement cosine similarity from scratch with NumPy.
- Calculate the score for every FAQ.
- Sort from highest to lowest.
- Add a zero-vector test.
- Try different vectors and observe how the angle changes the score.
Test Your Understanding
The direction or angle between two vectors.
The dot product in the numerator and the product of the two vector magnitudes in the denominator.
Their cosine similarity is 1.
From -1 to 1.
No. It is a similarity or ranking signal, not proof of correctness.
30-Second Recap
Key Takeaways
- Cosine similarity focuses on the angle between vectors.
- Normalization reduces the effect of raw vector magnitude.
- It is a common comparison method for embedding-based retrieval.
- Never treat a similarity score as a universal relevance threshold.
- In RAG, similarity helps retrieve candidate context; it does not replace evaluation or answer verification.