Distance Metrics
A deep dive into how vector spaces measure separation — Euclidean, Manhattan, and Chebyshev — why the choice of metric matters, and how nearest-neighbour retrieval, clustering, and anomaly detection all depend on it.
Distance: How the Scholar Measures Physical Separation
When walking between two bookshelves in the library, Euclidean distance ($L_2$) is the straight laser beam connecting the two coordinates, while Manhattan distance ($L_1$) is walking along grid aisles. However, in high-dimensional spaces ($d > 500$), raw distance is vulnerable to magnitude stretching (long texts having bigger vectors), which is why direction (Cosine Similarity) is often preferred.
IntroductionDistance as a scalar rule for separation
A distance metric is a rule that takes two points in a vector space and returns a single non-negative number representing how far apart they are. The smaller the number, the closer the points. The metric you choose changes what "close" and "far" mean — two points can be near each other under one metric and far apart under another.
Same point (distance = 0)
Any point is zero distance from itself under every valid metric. This is a mathematical requirement: $d(x, x) = 0$ for all $x$.
Farther apart (distance grows)
As coordinates diverge, distance increases. But the rate and shape of that growth differs per metric — that difference is what you are choosing when you pick Euclidean vs Manhattan.
- $x = [1, 2]$, $y = [4, 6]$: Euclidean distance = 5, Manhattan distance = 7
- Same two points — different metric — different number
- Your model's behaviour changes when you change the metric
WhyWhy distance measurement powers AI systems
Many core AI tasks are fundamentally nearest-neighbour problems in disguise. Once data is embedded as vectors, the algorithm reduces to: "which vectors are closest to this query?" A single scalar distance lets you rank an entire dataset in one pass.
- Retrieval: Find documents whose embeddings are closest to a query embedding (RAG, semantic search).
- Classification: k-NN classifiers assign labels based on the majority label among the $k$ nearest training examples.
- Clustering: k-means and DBSCAN group points by within-cluster distance.
- Anomaly detection: A point far from all known reference vectors is flagged as an outlier.
- Recommendation: Suggest items whose vectors are close to a user's preference vector.
IntuitionCity blocks vs as-the-crow-flies
The best intuition is a city grid. Imagine navigating from one intersection to another:
- Euclidean distance (L2): How far is it as the crow flies? Draw a straight diagonal line between the two points. That length is the Euclidean distance. It does not care about roads.
- Manhattan distance (L1): How far must you walk if you must follow the grid, turning only north/south or east/west? Add up the horizontal and vertical blocks you must travel. No shortcuts.
- Chebyshev distance (L∞): How many moves does a chess king need? The king can move one step in any of 8 directions. The total moves needed equals the largest single-axis gap.
Same two points: A = (1, 2) → B = (4, 6) Euclidean: straight diagonal line, length = √( (4-1)² + (6-2)² ) = √25 = 5 Manhattan: walk right 3 blocks + walk up 4 blocks = 7 Chebyshev: max(|4-1|, |6-2|) = max(3, 4) = 4
Close means two vectors point in a similar direction, or sit near each other. The model has learned that those two tokens are used in similar ways, so it treats them as similar in meaning.
- Cosine similarity — the angle between the vectors. Close = value near 1.
- Euclidean distance — the straight-line gap between the points. Close = small number.
- Dot product — direction and length together. Close = large number.
king and queen end up close because they appear in similar contexts; cat and carburetor end up far apart. Close means "used in similar ways", which is not always "means the same" — opposites like hot and cold can end up close. A static embedding gives bank one position for both meanings; a contextual embedding moves it nearer to money or nearer to river, depending on the sentence.
One dimension on its own has no human-readable meaning. Closeness only makes sense when you compare whole vectors.
TheoryThe L-p family of distance metrics
All three common metrics belong to the Minkowski family, parameterised by $p$: $d_p(x,y) = \left(\sum_{i=1}^{n} |x_i - y_i|^p \right)^{1/p}$. Setting $p$ to different values gives the familiar named metrics.
| Metric | Norm | Formula | Geometric meaning | Best when |
|---|---|---|---|---|
| Euclidean (L2) | $p=2$ | $\sqrt{\sum_i (x_i - y_i)^2}$ | Straight-line distance; penalises large individual deviations quadratically | Features are on the same scale; geometric gap in space matters |
| Manhattan (L1) | $p=1$ | $\sum_i |x_i - y_i|$ | Sum of axis-aligned steps; penalises all deviations equally | Sparse features; many zero dimensions; you want robustness to outlier coordinates |
| Chebyshev (L∞) | $p \to \infty$ | $\max_i |x_i - y_i|$ | Largest single-axis gap; the dominant dimension drives the result | When one dimension can make the entire decision (e.g. chess king movement) |
How It WorksCoordinate differences → scalar aggregation
All distance computations follow the same two-stage pattern: first compute per-coordinate differences, then aggregate them into a single scalar according to the metric's rule.
CalculateManual worked example step by step
Walk through two worked examples in detail so the mechanics become automatic.
2D example: $x = [1, 2]$, $y = [4, 6]$
3D example: $a = [0, 1, 0]$, $b = [3, 1, 4]$
VisualizeSame pair, different paths
The Mermaid diagram below shows how the same two points A=(1,2) and B=(4,6) produce three different numbers depending on which rule you apply.
Euclidean (L2)
Draw a straight diagonal line from A to B. Measure its length. This is the geometric, physical notion of distance. The "unit ball" around any point is a circle (sphere in 3D).
Manhattan (L1)
Walk along the grid — you can only move horizontally or vertically. The total distance is the sum of those moves. Multiple paths exist, all with the same total length. The "unit ball" is a diamond.
Chebyshev (L∞)
A chess king needs as many moves as the maximum of the horizontal or vertical gap. The "unit ball" is a square. It ignores all but the worst single dimension.
High-dimensional intuition
In 768-dimensional embedding space you cannot visualise this. But the formulas scale exactly the same way — you just sum or max over 768 coordinate differences instead of 2.
CodePython implementations from scratch + NumPy
First, implement each metric from scratch so you understand every step. Then see the idiomatic NumPy and SciPy equivalents used in production code.
import math
import numpy as np
from scipy.spatial import distance as scipy_dist
# ── From scratch ────────────────────────────────────────────────────────────
def euclidean(x: list[float], y: list[float]) -> float:
"""L2 distance: straight-line separation in n-dimensional space."""
return math.sqrt(sum((xi - yi) ** 2 for xi, yi in zip(x, y)))
def manhattan(x: list[float], y: list[float]) -> float:
"""L1 distance: sum of absolute coordinate differences."""
return sum(abs(xi - yi) for xi, yi in zip(x, y))
def chebyshev(x: list[float], y: list[float]) -> float:
"""L-infinity distance: maximum absolute coordinate difference."""
return max(abs(xi - yi) for xi, yi in zip(x, y))
# ── Test ─────────────────────────────────────────────────────────────────────
a = [1, 2]
b = [4, 6]
print(f"L2 = {euclidean(a, b)}") # 5.0
print(f"L1 = {manhattan(a, b)}") # 7
print(f"L∞ = {chebyshev(a, b)}") # 4
# ── NumPy equivalents ────────────────────────────────────────────────────────
A = np.array([1.0, 2.0])
B = np.array([4.0, 6.0])
print(np.linalg.norm(A - B)) # Euclidean → 5.0
print(np.linalg.norm(A - B, ord=1)) # Manhattan → 7.0
print(np.linalg.norm(A - B, ord=np.inf)) # Chebyshev → 4.0
# ── SciPy: works on any-length arrays ────────────────────────────────────────
print(scipy_dist.euclidean(A, B)) # 5.0
print(scipy_dist.cityblock(A, B)) # 7.0
print(scipy_dist.chebyshev(A, B)) # 4.0
# ── High-dimensional example (typical embedding size) ─────────────────────
rng = np.random.default_rng(42)
v1 = rng.standard_normal(768)
v2 = rng.standard_normal(768)
print(f"768-dim L2 = {np.linalg.norm(v1 - v2):.4f}")
# Expect ~39–41 for random standard normal vectors in 768 dims
What the scratch code reveals
The core loop is identical for all three metrics — only the aggregation function changes: sqrt(sum(sq)) vs sum(abs) vs max(abs). This is the Minkowski family in action.
Why NumPy/SciPy in production
np.linalg.norm is vectorised BLAS, orders of magnitude faster on large arrays. scipy.spatial.distance adds pairwise distance matrices and many other metrics (cosine, minkowski, hamming, etc.).
Hands-onInteractive distance calculator
🔍 Behind-the-Scenes: Mathematical Pipeline of All 4 Distance Metrics
CompareDistance vs Similarity — two sides of the same coin
Distance and similarity express the same relationship with opposite sign conventions. Many systems (especially vector databases) expose one as their primary interface and let you derive the other.
| Property | Distance | Similarity (e.g. cosine) |
|---|---|---|
| Identical vectors | 0 (minimum) | 1.0 (maximum) |
| Completely different | Large (unbounded for L2/L1) | 0.0 or −1.0 (lower bound) |
| Direction of "better" | Lower is closer | Higher is more alike |
| Scale sensitivity | L2 and L1 depend on vector magnitude | Cosine similarity is magnitude-invariant |
| Conversion | $d = 1 - \text{sim}$ (for cosine) | $\text{sim} = 1 - d$ (only for bounded metrics) |
| Vector DB default | Euclidean (FAISS default), Inner product | Cosine (many cloud vector DBs) |
ApplyDistance in real AI systems
k-NN Classification
For each test point, compute L2 distance to every training point. Take the $k$ closest. Assign the majority label. L2 is the standard choice because squared differences emphasise genuine feature gaps.
k-Means Clustering
The assignment step measures L2 distance from each point to each centroid. The update step minimises total squared L2 distance within clusters. L2 is baked into the k-means objective function.
RAG / Semantic Search
Encode the query and all documents as dense embeddings (768-dim). Retrieve the top-$k$ documents by cosine similarity (often equivalent to L2 on normalised vectors). Return the closest matches.
Anomaly Detection
Build a reference distribution of "normal" vectors. Flag any new vector whose L2 distance from the nearest reference exceeds a threshold. Points far from everything seen during training are anomalies.
LimitationsWhen distance breaks down
Distance metrics only produce meaningful results when the underlying vector representation is meaningful. Several failure modes are common:
- Feature scaling destroys L2: If one feature ranges from 0 to 1,000 and another from 0 to 1, the large-scale feature dominates all distances. Standardise or normalise first.
- Magnitude confusion: Raw L2 treats a short vector and a long vector as far apart even if they point in the same direction. Use cosine similarity when direction matters more than magnitude.
- Curse of dimensionality: In very high dimensions, all pairwise distances tend to become similar (concentration of measure). The contrast between the nearest and farthest neighbour shrinks, making nearest-neighbour search less meaningful.
- Metric mismatch: Euclidean distance on one-hot vectors is dominated by which bits happen to be set. It does not reflect semantic similarity the way dense embeddings do.
- Different metrics produce different rankings: The nearest neighbour under L2 may not be the nearest neighbour under L1. Your evaluation metric must match your retrieval metric.
Common mistake
Training k-NN on unnormalised features with very different scales. L2 will be dominated by the high-scale feature regardless of the other features.
Fix
Apply StandardScaler or MinMaxScaler before computing any distance. For dense embeddings, normalise to unit length so L2 and cosine rankings agree.
Feynman ChallengeCan you explain it simply?
Use the "city grid" metaphor to explain all three metrics to someone who has never studied linear algebra:
- Euclidean: The straight-line flight path between two cities — ignores all roads.
- Manhattan: The walking distance in a city grid — you can only travel along streets, adding up every block.
- Chebyshev: How many chess-king moves to reach the destination — the king can step diagonally, so the worst single-axis gap limits you.
- Same two points, different rules, different numbers. "Distance" is meaningless without stating which rule.
- In AI, you use whichever rule best captures what "similar" means for your task.
Common misconceptions to tackle:
- "L2 is always better than L1" — No: L1 is more robust to outlier coordinates and preferred for sparse features.
- "Distance tells me semantic meaning directly" — No: it tells you geometric distance in the embedding space. Semantic meaning depends on how well the embedding was trained.
- "All vector databases use the same distance metric" — No: each system has defaults and options; match the metric to how your embeddings were trained.
- "I can mix L2 and cosine similarity rankings in the same retrieval pipeline" — No: they are on incompatible scales and cannot be directly compared or averaged.
- "Normalising vectors makes L2 and cosine equivalent" — Yes, this one is true: when both vectors are unit-length, minimising L2 is equivalent to maximising cosine similarity.
BuildMini-projects to cement understanding
🔨 Mini-Projects
1 · Nearest-neighbour playground
Generate 20 random 2D points. Place a query point at (0, 0). Compute L2 and L1 distances from the query to every point. Sort and display the top 5 nearest neighbours under each metric. Note where the rankings differ.
2 · Metric comparison on embeddings
Take 10 sentences, encode them with a sentence-transformer. Rank all pairwise distances under L2 vs cosine. Find at least 2 pairs that rank differently under the two metrics and explain why.
3 · Feature scaling experiment
Build a 3-feature dataset where feature 1 ranges 0–1000 and features 2–3 range 0–1. Compute L2 distances raw. Then apply StandardScaler and recompute. Show how scaling changes the nearest-neighbour ranking.
SummaryEverything in one place
- Distance = scalar separation under a specific rule. It always requires specifying both the vector representation and the metric.
- L2 (Euclidean): Straight-line distance. Penalises large individual deviations quadratically. Most common default in ML.
- L1 (Manhattan): Sum of absolute differences. Robust to outlier coordinates. Good for sparse features.
- L∞ (Chebyshev): Maximum absolute coordinate difference. The single worst dimension determines the result.
- Metric choice matters: Same pair of vectors, different metrics, different rankings. There is no universally "best" metric — it depends on your data and task.
- Feature scaling is non-negotiable with L2/L1: Unscaled features make distance measurements meaningless when features have different ranges.
- High-dimensional warning: Curse of dimensionality can cause distance concentration — all points appear equally far apart, degrading nearest-neighbour quality.
- Distance vs similarity: They express the same relationship with opposite polarity. Cosine similarity is magnitude-invariant; L2 is not.
- Next: Similarity metrics (cosine, dot product) → how vector databases index and search at scale.
L2 / L1
Both members of the L-p Minkowski family. L2 squares differences before summing; L1 uses absolute values. L2 ≤ L1 always.
Metric matters
The distance metric is a design decision. It shapes which points count as "near" and therefore every downstream clustering, retrieval, or classification result.
Use case
k-NN, k-means, RAG retrieval, anomaly detection — all reduce to "find nearest vectors." The metric is your first architectural choice.
Normalisation
Unit-length normalisation makes L2 distance equivalent to cosine distance, collapsing two choices into one consistent behaviour.
