Beginner6 min read3 of 10

Similarity Metrics: Cosine, Euclidean, Dot Product

How the three main distance functions work, when each one wins, and the key insight that cosine ignores magnitude — which is almost always what you want for text.

Similarity Metrics: Cosine, Euclidean, Dot Product

Two vectors sit in high-dimensional space. How do you measure whether they're "close"? The answer depends on what you care about — direction or magnitude.

All similarity metrics compared side by side

The core intuition

Imagine two arrows from the origin:

  • Cosine similarity asks: Are they pointing in the same direction?
  • Euclidean distance asks: How far apart are their tips?
  • Dot product asks: Are they pointing the same way AND how long are they?

Cosine similarity — the default for text

Cosine similarity measures the angle between two vectors, completely ignoring their length.

cosine(a, b) = (a · b) / (|a| × |b|) Range: [-1, 1] 1.0 = identical direction (same meaning) 0.0 = perpendicular (unrelated) -1.0 = opposite directions (opposite meaning)

Why magnitude doesn't matter for text: A short tweet and a long article about the same topic should be equally similar to a query. Cosine handles this correctly — the tweet isn't "less relevant" just because it has fewer words.

vec1 = [1, 2, 3] ← short document about topic X vec2 = [2, 4, 6] ← same document, longer version (2× scale) vec3 = [3, 1, -2] ← different topic entirely cosine(vec1, vec2) = 1.0 ← perfect match (correct — same meaning) cosine(vec1, vec3) = 0.27 ← distant (correct — different meaning)

If you used Euclidean distance here, vec1 and vec2 would appear far apart (distance = 3.74), which is wrong.

Euclidean distance — when magnitude matters

Euclidean is the straight-line distance between vector tips:

euclidean(a, b) = √( Σ(ai - bi)² ) Range: [0, ∞) 0 = identical vectors larger = more different

Use Euclidean when the size of the vector carries real meaning:

  • Physical measurements (coordinates, sensor readings)
  • Count data (word frequency histograms)
  • Recommendation systems where activity level matters

For most text search, Euclidean is the wrong choice because document length pollutes the signal.

Dot product — direction + magnitude combined

dot(a, b) = Σ(ai × bi) Range: (-∞, ∞) larger = more similar

Dot product rewards both directional alignment and vector magnitude. This makes it useful when you want to give higher-weight results to "more prominent" items — for example, in collaborative filtering where users with more ratings should score higher than users with few.

For text search: only use dot product when your embedding model was specifically trained with a dot product objective, or when your vectors are already normalized (in which case dot product equals cosine similarity).

[Definition] When vectors are normalized to unit length (L2 norm = 1), dot product and cosine similarity give identical results. Always normalize your embeddings before indexing — then your index can use the faster dot product path internally while you reason about cosine semantically.

How cosine scores are reported

Raw cosine similarity ranges from -1 to 1, but search engines don't return this value directly. The score you see in search results is transformed to be monotonically decreasing — so that higher score always means more relevant, and the score never goes negative:

@search.score = 1 / (1 + cosine_distance) where cosine_distance = 1 - cosine_similarity

This maps cosine similarity to a score range of 0.333 – 1.00:

  • Score 1.00 = perfect match (cosine similarity = 1.0)
  • Score 0.50 = cosine similarity = 0.0 (unrelated)
  • Score 0.333 = cosine similarity = -1.0 (opposite)

If you need the original cosine value from a search score:

cosine_similarity = 1 - ((1 - score) / score)

This is useful for setting quality thresholds — e.g., discard any result with cosine similarity below 0.7.

Quality benchmark across metrics

From a standard semantic search evaluation:

MetricNDCG@10Best for
Cosine similarity0.87Text and semantic search
Dot product0.84Models trained with dot objective
Euclidean (L2)0.82Physical / count data

Distance metric overview

Manhattan and Chebyshev (specialist uses)

Manhattan (L1): Sum of absolute differences. Less sensitive to outliers than Euclidean. Used in anomaly detection and some clustering algorithms.

Chebyshev (L∞): Maximum absolute difference across any single dimension. Used in worst-case analysis — robotics, logistics, board-game pathfinding.

You'll rarely need these for text search.

Decision guide

Metric selection guide

When in doubt:

  1. Normalize your vectors to unit length
  2. Use cosine similarity (or dot product — they're identical at unit length)
  3. Only deviate when you have a specific reason tied to your data type

That's the default that works across 95% of text search use cases.