Contents
, where and is a symmetric positive-definite covariance matrix
Deep Breakdown
What it tells me (Situation Awareness): The multivariate Gaussian extends the bell curve to correlated variables at once. The mean vector sets the centre; the covariance matrix sets each variable's spread (diagonal) and how pairs move together (off-diagonal). The heart of the formula is the quadratic form , the squared Mahalanobis distance: a distance measured in standard deviations that also accounts for correlation, so a point that breaks the usual relationship between variables looks far away even if each coordinate looks normal on its own. Contours of equal density are ellipses (ellipsoids) shaped by the eigenvectors of . Two properties make it uniquely convenient: every marginal is Gaussian (just drop rows and columns of and ) and every conditional is Gaussian with a closed-form mean and variance. In DA/DS: multivariate anomaly and fraud detection via Mahalanobis distance, Gaussian Mixture Models, LDA and QDA classifiers, Gaussian processes, Kalman filters, the latent space of VAEs, portfolio returns in finance, and the sampling distribution of regression coefficients .
Flowchart
Real-world use
Where it is used
Fraud and anomaly detection on several transaction features, customer segmentation with Gaussian Mixture Models, LDA/QDA classification, Gaussian process regression for demand forecasting and Bayesian optimisation, sensor fusion (Kalman filters), portfolio risk (correlated asset returns), VAE latent spaces, and confidence ellipses for jointly estimated parameters.
Problem it solves
Models several continuous variables jointly, capturing their correlations, so I can score how typical a whole profile is, predict some variables from others, and simulate realistic correlated scenarios instead of treating features as independent.
How it solves the problem
The covariance matrix encodes all pairwise linear relationships. Inverting it in the exponent rescales and de-correlates the deviation , so the density depends only on the Mahalanobis distance. The determinant measures the volume of the cloud and keeps the total probability equal to 1. Partitioning and gives marginals and conditionals in closed form.
Example in a business
An e-commerce risk team models (standardised order value, standardised items per order) as with . An order at has (distance ), far below the 99% chi-square cut-off of for , so it is normal. Knowing items also updates the expected order value from 0 to , with conditional variance instead of .
The formula, piece by piece
- : a -dimensional observation (one row of features).
- : mean vector, the centre of the cloud; .
- : covariance matrix; is the variance of feature and the covariance of features and .
- : precision matrix; a zero entry means two variables are conditionally independent given the rest.
- : squared Mahalanobis distance .
- : density falls off with distance, equally along each ellipse.
- : determinant, the generalised variance (volume of the ellipsoid).
- : normalising constant that grows with dimension.
- With the formula collapses to the familiar .
- Marginal: for a block , .
- Conditional: .
The formula in words
"The density of a point depends on how many correlation-adjusted standard deviations it sits from the centre: square that Mahalanobis distance, halve it, exponentiate its negative, and divide by a constant that depends on the dimension and the volume of the covariance." Tiny example: with (independent unit-variance features) in , the point has and density .
Critical Concepts
- Mahalanobis vs Euclidean: Euclidean distance ignores scale and correlation; Mahalanobis divides them out. Under the model, , which gives principled outlier thresholds.
- Covariance must be positive definite: with more features than samples, or perfectly collinear features, is singular. Use shrinkage (Ledoit-Wolf) or regularisation.
- Marginals are easy: pick the sub-vector of and sub-matrix of .
- Conditionals are linear regression: the conditional mean is linear in the observed variables and the conditional variance never exceeds the marginal one. Gaussian processes and Kalman filters are built on this.
- Uncorrelated implies independent only for jointly Gaussian variables, not in general.
- Sampling: with (Cholesky) and .
- Work in log space: avoids underflow in high dimensions and is what GMMs and QDA actually compute.
- Real data has fat tails: financial returns and fraud data often violate Gaussian tails; check with QQ-plots of against .
Step-by-step calculation (tiny example)
Step 1: Set up , , , .
Step 2: Determinant and inverse . .
Step 3: Mahalanobis distance .
Step 4: Density ; normaliser . .
Step 5: Marginal and conditional Marginal . Given : mean , variance .
Code examples
Beginner example (Python)
import numpy as np
from scipy.stats import multivariate_normal
mu = np.array([0.0, 0.0])
Sigma = np.array([[1.0, 0.5], [0.5, 2.0]])
x = np.array([1.0, 1.0])
diff = x - mu
d2 = diff @ np.linalg.inv(Sigma) @ diff
print(f"det(Sigma) = {np.linalg.det(Sigma):.2f}") # 1.75
print(f"Mahalanobis D^2 = {d2:.4f}") # 1.1429
print(f"Density = {multivariate_normal(mu, Sigma).pdf(x):.4f}") # 0.0679
# Conditional of X1 given X2 = 1
cond_mean = mu[0] + Sigma[0, 1] / Sigma[1, 1] * (x[1] - mu[1])
cond_var = Sigma[0, 0] - Sigma[0, 1] ** 2 / Sigma[1, 1]
print(f"X1 | X2=1: mean = {cond_mean:.2f}, var = {cond_var:.3f}") # 0.25, 0.875Beginner example (R)
mu <- c(0, 0)
Sigma <- matrix(c(1, 0.5, 0.5, 2), nrow = 2)
x <- c(1, 1)
d2 <- mahalanobis(x, center = mu, cov = Sigma) # 1.1429
dens <- exp(-d2 / 2) / (2 * pi * sqrt(det(Sigma))) # 0.0679
cat(sprintf("D^2 = %.4f | density = %.4f\n", d2, dens))
cat(sprintf("99%% cut-off for d=2: %.2f\n", qchisq(0.99, df = 2))) # 9.21Professional example (Python)
import numpy as np
from scipy.stats import chi2
from sklearn.covariance import MinCovDet
def mahalanobis_outliers(X: np.ndarray, alpha: float = 0.01) -> tuple[np.ndarray, float]:
"""Flag multivariate outliers using a robust Gaussian fit.
MinCovDet estimates mu and Sigma while ignoring the most extreme points,
so the fraud cases do not inflate the covariance they are judged against.
Args:
X: (n, d) feature matrix.
alpha: Tail probability for the chi-square threshold.
Returns:
Boolean outlier mask and the D^2 threshold used.
"""
robust = MinCovDet(random_state=42).fit(X)
d2 = robust.mahalanobis(X) # squared distances
threshold = chi2.ppf(1 - alpha, df=X.shape[1])
return d2 > threshold, float(threshold)
rng = np.random.default_rng(42)
mu = np.array([0.0, 0.0])
Sigma = np.array([[1.0, 0.5], [0.5, 2.0]])
normal_orders = rng.multivariate_normal(mu, Sigma, size=2000)
# Fraud: each coordinate looks ordinary, but the combination breaks the correlation
fraud = np.array([[2.0, -2.5], [-2.0, 2.8], [2.2, -2.0]])
X = np.vstack([normal_orders, fraud])
mask, thr = mahalanobis_outliers(X, alpha=0.01)
print(f"Chi-square 99% threshold (d=2): {thr:.2f}") # 9.21
print(f"Flagged among normal orders: {mask[:-3].mean():.2%} (expected about 1%)")
print(f"Fraud cases flagged: {mask[-3:].sum()} of 3")
# Compare with a naive per-feature z-score rule (|z| above 3 on any feature)
z = (X - X.mean(axis=0)) / X.std(axis=0)
print(f"Fraud flagged by per-feature |z| above 3: {(np.abs(z[-3:]) > 3).any(axis=1).sum()} of 3")Source: domain knowledge