Contents
Deep Breakdown
What it tells me (Situation Awareness): The Minkowski distance is the general norm-based distance family. Every standard distance metric you know is a special case: is Manhattan, is Euclidean, is Chebyshev. The parameter controls how much weight is given to large vs. small differences: large increasingly dominates on the single largest component difference. In DA/DS: Minkowski distance is used in -NN classification/regression, clustering (k-means with custom distance), anomaly detection, and any pipeline where the geometry of the feature space matters. Choosing is a hyperparameter that affects model sensitivity to outlier features.
Flowchart
Real-world use
Where it is used
-NN with tunable (scikit-learn KNeighborsClassifier(metric='minkowski', p=p)), distance-based clustering, feature space analysis, and grid search over as a hyperparameter in any distance-based model.
Problem it solves
Different feature spaces have different geometric properties. Euclidean distance penalizes large deviations quadratically. Manhattan is robust to this. Chebyshev captures the worst-case deviation. Minkowski unifies these under one formula so you can tune or search over the right geometry for your data.
How it solves the problem
By varying , the shape of the "unit ball" (set of all points at distance 1) changes from a diamond (), to a circle (), to a square (). The appropriate depends on the domain: high-dimensional sparse data tends to prefer (Manhattan); dense continuous data tends to prefer (Euclidean).
Example in a business
A DS trains a -NN churn classifier on customer behavioral features and tunes via cross-validation. For (Manhattan) the model focuses on total behavioral deviation; for (Euclidean) it weights larger deviations more strongly. The optimal is selected by comparing validation AUC across .
The formula, piece by piece
- : the Minkowski distance between vectors
- : absolute difference of the -th feature
- : raising to power controls sensitivity to large differences; large = more weight on the biggest gap
- : sum over all dimensions
- : the -th root brings the result back to the original scale (undoes the power)
- : the constraint that makes this a proper metric (triangle inequality holds iff , by Minkowski's inequality)
- Special cases: (Manhattan), (Euclidean), gives (Chebyshev)
The formula in words
"Compute the absolute difference in each coordinate. Raise each to the -th power (amplifying large gaps more for larger ). Sum them up. Then take the -th root to restore the scale. The result is a distance where controls how much the biggest gaps dominate." Tiny example: , .
- : .
- : .
- : .
Critical Concepts
- required for metric: for , the triangle inequality fails (it is a semimetric, not a metric).
- Curse of dimensionality: as , Minkowski distances concentrate — all pairwise distances become similar. This makes distance-based models unreliable in very high dimensions.
- is rotation-invariant: only (Euclidean) is invariant under rotation of the coordinate system. and others depend on axis alignment.
- limit: .
- Weighted Minkowski: allows feature importance weighting.
- scikit-learn:
KNeighborsClassifier(metric='minkowski', p=p)defaults to (Euclidean).
Step-by-step calculation (tiny example)
Step 1: Set up vectors and choose , . Differences: , , .
Step 2: Compute for (Manhattan) .
Step 3: Compute for (Euclidean) .
Step 4: Compute for . As increases, the result approaches (Chebyshev).
Code examples
Beginner example (Python)
import numpy as np
def minkowski_distance(x: np.ndarray, y: np.ndarray, p: float) -> float:
"""Compute Minkowski distance D_p(x, y) for given p >= 1."""
if p == float('inf'):
return float(np.max(np.abs(x - y)))
return float(np.sum(np.abs(x - y) ** p) ** (1.0 / p))
x = np.array([1.0, 2.0, 3.0])
y = np.array([4.0, 0.0, 6.0])
for p_val in [1, 2, 3, 10, float('inf')]:
dist = minkowski_distance(x, y, p_val)
print(f"p={p_val:>5}: D_p = {dist:.4f}") # Compare with scipy reference
from scipy.spatial.distance import minkowski
print(f"\nscipy minkowski p=2: {minkowski(x, y, p=2):.4f}")
print(f"scipy minkowski p=1: {minkowski(x, y, p=1):.4f}")Beginner example (R)
# -- Minkowski distance for varying p ---
minkowski_dist <- function(x, y, p) { if (is.infinite(p))
return(max(abs(x - y))) sum(abs(x - y)^p)^(1 / p)
}
x <- c(1, 2, 3)
y <- c(4, 0, 6)
for (p_val in c(1, 2, 3, 10, Inf)) { dist <- minkowski_dist(x, y, p_val)
cat(sprintf("p = %5s: D_p = %.4f\n", ifelse(is.infinite(p_val), "Inf", as.character(p_val)), dist))
}Professional example (Python)
import numpy as np
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
from sklearn.model_selection import StratifiedKFold, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.datasets import make_classification
np.random.seed(42) # -- Business scenario: tune Minkowski p as hyperparameter for kNN churn model ---
X, y = make_classification( n_samples=800, n_features=10, n_informative=6, n_redundant=2, random_state=42 )
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
P_VALUES = [1, 1.5, 2, 3, 5]
CV = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
K_NEIGHBORS = 7
results = []
for p_val in P_VALUES:
clf = KNeighborsClassifier(n_neighbors=K_NEIGHBORS, metric='minkowski', p=p_val)
scores = cross_val_score(clf, X_scaled, y, cv=CV, scoring='roc_auc')
results.append({ "p": p_val, "norm_name": {1: "Manhattan", 2: "Euclidean"}.get(p_val, f"L{p_val}"), "mean_auc": round(scores.mean(), 4), "std_auc": round(scores.std(), 4), })
df = pd.DataFrame(results)
print(f"kNN (k={K_NEIGHBORS}) Minkowski distance hyperparameter search:")
print(df.to_string(index=False))
best_row = df.loc[df["mean_auc"].idxmax()]
print(f"\nBest: p={best_row['p']} ({best_row['norm_name']}), AUC={best_row['mean_auc']:.4f}")Source: domain knowledge