Scrapeless Wiki

What Is Cosine Similarity? – Definition and How It Works

Informational P2 what is cosine similarity

Learn what cosine similarity measures, why it ignores magnitude, how normalisation turns it into a dot product, and its limits.

Cosine similarity measures the angle between two vectors, ignoring their length. It is the standard similarity metric for text embeddings.

1. The Definition

cos(A, B) = (A Β· B) / (β€–Aβ€– β€–Bβ€–)

The dot product divided by the product of the magnitudes. The result runs from -1 to 1:

Value Meaning
1 Same direction β€” maximally similar
0 Orthogonal β€” unrelated
-1 Opposite direction

In practice, modern text embeddings rarely produce negative similarities, so the useful range is roughly 0 to 1.

2. Why Ignoring Magnitude Is the Point

Two documents about the same topic, one three paragraphs and one thirty, produce embeddings pointing in a similar direction with different magnitudes.

Euclidean distance would call them far apart because of the length difference. Cosine similarity calls them similar because it only asks which way the vectors point.

For text that is almost always what you want β€” topic, not volume.

3. Normalise Once, Then It's Just a Dot Product

If every vector is normalised to unit length, the denominator becomes 1 and cosine similarity reduces to the dot product:

import numpy as np

def normalize(m):
    return m / np.linalg.norm(m, axis=1, keepdims=True)

docs = normalize(np.asarray(doc_vectors, dtype=np.float32))
q    = normalize(np.asarray([query_vector], dtype=np.float32))[0]

scores = docs @ q                      # cosine similarity, one matrix multiply
top = np.argsort(-scores)[:10]

Normalising at index time rather than at query time is the standard optimisation: it turns every subsequent comparison into a plain dot product, which is why vector databases store normalised vectors and offer "inner product" as a metric.

4. Cosine, Dot Product, Euclidean

Metric Sensitive to magnitude Typical use
Cosine No Text embeddings
Dot product Yes Normalised vectors, or where magnitude is meaningful
Euclidean (L2) Yes Spatial data, some image embeddings

On normalised vectors all three rank identically, which is why the choice often does not matter β€” as long as the vectors really are normalised. Mixing normalised and unnormalised vectors in one index silently corrupts ranking.

5. What the Number Does Not Mean

It is not a probability. 0.85 does not mean 85% likely relevant.

It is not comparable across models. One embedding model's 0.7 may be another's 0.9 for the same pair. Thresholds must be calibrated per model.

It is not comparable across query types. Short queries tend to produce lower similarities than long ones against the same corpus.

High similarity is not relevance. Two chunks of boilerplate are highly similar to each other and useless to the user.

That last point is why a similarity threshold is a weak relevance filter, and why reranking exists.

6. The Practical Traps

  • Unnormalised vectors in an index that assumes normalisation β€” ranking silently degrades.
  • A hard threshold ported between models or corpora.
  • float32 vs float64 mismatches in comparison code.
  • Near-duplicate documents dominating results, since they are similar to everything the original was.
  • Very short chunks producing unstable directions, so similarity is noisy.

7. Using It Well

  1. Normalise at index time; treat the metric as a dot product thereafter.
  2. Calibrate any threshold on your own data, with your own model.
  3. Deduplicate results β€” near-identical chunks otherwise fill the top ranks.
  4. Rerank the top candidates with a stronger model rather than trusting similarity alone.
  5. Combine with a lexical score, since cosine alone misses exact identifiers.

8. Summary

Cosine similarity is the angle between two vectors, ignoring magnitude, which suits text because it compares topic rather than length.

Normalise vectors at index time so the metric becomes a plain dot product, and remember the score is not a probability and not portable between models β€” so calibrate thresholds on your own data, deduplicate near-identical results, and rerank rather than treating similarity as relevance.