Embeddings
Intermediate 11 min read Embeddings

Cosine Similarity & Distance

Measuring direction, not size

Cosine similarity measures orientation, not magnitude: identical direction = 1 regardless of length. Choosing the right metric — cosine vs Euclidean vs dot — decides whether your thresholds mean anything.

cosine similarityeuclideandot productdistance metricnormalization
Prerequisites: Embedding Basics
Before we start

What you will learn

  • Compute cosine, dot and Euclidean by hand
  • Explain why normalization matters
  • Choose a metric per use case
Introduction

What is this?

Cosine similarity measures the angle between vectors, ignoring magnitude: perfectly aligned = 1, orthogonal = 0, opposite = −1 (for standardized embeddings, near 0..1). Euclidean uses actual distance; dot product mixes magnitude and direction. L2-normalized vectors make all three family-friendly — but they are only comparable within the same normalization convention.

Motivation

Why do you need it?

  • Cosine dominates semantic similarity because magnitude (word length/complexity) is noise.
  • Thresholds ('similarity > 0.78') mean nothing without the metric+normalization defined.
  • Vector DBs may index with one metric — choose before ingest, not after.
  • Clustering/DEDUP algorithms assume a consistent distance everywhere.
Think about it

Mental model

Imagine

Comparing two arrows by direction only

Think of

Cosine similarity

A long arrow pointing NE and a short arrow pointing NE describe the same trend; their lengths are noise. Cosine throws away the shaft lengths and reports how aligned the directions are. Your application then decides whether 'aligned' is 'similar'.

Mechanics

How it works

  • Cosine(a, b) = (a·b) / (|a||b|) — normalized dot of directions.
  • Euclidean distance = |a − b|; direct geometric distance in the space.
  • Dot = Σ a_i b_i — no normalization; magnitude bleeds in.
  • L2 normalization: v = v / |v| makes cosine = dot product and Euclidean rank-equivalent to 2−2·cos.
  • Which to pick follows your storage + train conventions and threshold semantics.

Metric decision tree.

Normalized?
Direction only
Magnitude matters
Storage
Hands-on

Examples

Metric comparison

Metric comparison
import numpy as np
a = np.array([2.0, 0.0])
b = np.array([1.0, 0.0]) # same direction, half length
cos = np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))
eucl = np.linalg.norm(a - b)
print("cosine:", round(float(cos), 3), "(same direction = 1)")
print("euclid:", round(float(eucl), 3), "(magnitude differs)")

Cosine ignores length; Euclidean does not. That difference is why cosine suits semantically-similar-but-differently-sized text.

Real world

In production

  • Set the vector index metric to cosine for semantics-first search.
  • Clustering with Euclidean on L2-normalized vectors ≈ cosine clustering.
  • Threshold tuning experiments log the exact metric per run.
Guidelines

Best practices

  • Normalize when you embed; keep the pipeline idempotent.
  • Document the metric in the index config and code review.
  • Tune thresholds on labeled pairs, not vibes.
  • Verify index metric == your query metric after migrations.
Watch out

Common mistakes

  • Cosine thresholds applied to non-normalized vectors.
  • Mixing Euclidean during clustering and cosine at query.
  • Assuming cosine ∈ [0,1] for raw embeddings (often negative for unrelated texts).
Root cause analysis

Common issues

Error
Index and query disagree on nearness
Root cause

Metric mismatch between index build and query

Fix

Standardize on one metric + normalization; rebuild index.

Error
Thresholds behave oddly after model swap
Root cause

New embedding model—different score distribution

Fix

Re-tune thresholds on a labeled sample after embedding model changes.

When things break

Debugging tips

  • Scores suddenly ~1 for everything → non-normalized long vectors or index metric mismatch.
  • Threshold '0.8' fails → check whether you normalized and which metric the index actually used.
  • Clustering islands look wrong → same root cause: metric inconsistency.
Interviews

Interview checkpoint

Practice

Hands-on lab

Cosine Is Direction, Not Length
20 min · beginner
In progress
Objectives
  • Normalize a vector to unit length
  • Prove dot-product-of-units equals cosine
  • Show length-invariance with a scaled example

Cosine Is Direction, Not Length

20 min · beginner

0/3 steps
0%
sandbox · Linux sandbox
$
Try these commands
Test yourself

Quick quiz

0/2
1

Cosine similarity focuses on…

2

After L2 normalization, cosine equals the dot product.

Go deeper

Official documentation