From 1D Normal to nD#
The univariate normal (Gaussian) has density:
A multivariate Gaussian (also called a multivariate normal) in is parameterised by a mean vector and a covariance matrix :
Notation: . The term is the Mahalanobis distance squared — it generalises the squared z-score to multiple dimensions.
Level sets are ellipsoids. The set of points where the density is constant satisfies — an ellipsoid centred at . The shape and orientation of the ellipsoid are determined by :
- Diagonal with equal entries: spherical level sets (isotropic).
- Diagonal with different entries: axis-aligned ellipses.
- Non-diagonal : tilted ellipses — the off-diagonal entries encode linear dependence between dimensions.
For , is just , and we recover the familiar bell curve.
Mean and Covariance#
The parameters and are exactly the mean and covariance:
- (an element-wise expectation: ).
- , where .
The covariance matrix is symmetric () and positive semidefinite (PSD): for any vector , .
Why PSD? Consider the variance of the scalar . This variance must be :
If were not PSD, there would exist some linear combination of the with negative variance — impossible. This connects to the Linear Algebra course: is a symmetric PSD matrix, so its eigenvalues are all , and the condition number governs how "stretched" the ellipsoid is along each eigen-direction.
Correlation from covariance: The correlation matrix has entries . Diagonal entries of are always 1; off-diagonals are in .
Worked example — 2D Gaussian. Let
Then , , , and the correlation is . The ellipse is centred at , stretched more horizontally (variance 4) than vertically (variance 1), and tilted because of the positive off-diagonal covariance.
Marginals and Conditionals#
Gaussians are closed under marginalisation and conditioning — if the joint is Gaussian, every marginal and conditional is also Gaussian. This is one reason Gaussians dominate statistical modeling.
Marginals#
If , then any subset of components is Gaussian. For a partition :
You simply extract the corresponding sub-vector of and sub-matrix of . No integration required. The other variables are "marginalised out" automatically.
Conditionals#
Given partitioned as , the conditional is:
Key observations:
- The conditional mean is a linear function of the observed — the "correction" adjusts based on how far is from its mean, scaled by covariance structure.
- The conditional covariance does not depend on the value . Conditioning always reduces (or leaves unchanged) variance — information never increases uncertainty.
- The Schur complement is always PSD (smaller than in the Loewner order).
Special case — bivariate. For with correlation :
If , the conditional variance shrinks to zero — knowing determines exactly. If , the conditional mean and variance are the marginal values (no information gained).
Whitening and Mahalanobis#
Whitening transforms correlated data into uncorrelated, unit-variance data. Given , the whitened variable is:
is the inverse matrix square root — it exists because is PSD. After whitening, each component of is independent standard normal.
The Mahalanobis distance between and the distribution is:
This is the Euclidean distance in the whitened space. It accounts for correlation and differing variances — a point far from the mean in a high-variance direction gets less "surprise penalty" than the same Euclidean distance in a low-variance direction. This is used in anomaly detection, clustering, and as a building block in Kalman filters.
Why Gaussians Dominate ML Modeling#
- Central Limit Theorem (Week 7): sums of many independent random variables become approximately Gaussian — errors, noise, and aggregate quantities are often near-normal.
- Closed under linear operations: if and , then . Linear transformations preserve Gaussianity.
- Conjugacy (Week 9): a Gaussian prior with a Gaussian likelihood yields a Gaussian posterior — Bayesian updates stay in the same family.
- Maximum entropy: among all distributions with a given mean and covariance, the Gaussian has the largest entropy — it is the "least informative" assumption consistent with those moments.
- Limitations: real data is often heavier-tailed, multimodal, or bounded. But Gaussians remain the default building block because of their mathematical tractability.
Given Σ = [[4, 1], [1, 1]] for a 2D Gaussian. Is Σ a valid covariance matrix? (Hint: check if it's positive semidefinite.)
Knowledge check#
If X = (X₁, X₂) is jointly Gaussian, the marginal distribution of X₁ is:
Browser lab#
Sample a 2D Gaussian, plot scatter with ellipse level curves, and show a conditional slice histogram.
import numpy as np
import matplotlib.pyplot as plt
from numpy.linalg import eigh
rng = np.random.default_rng(42)
n = 3000
mu = np.array([3.0, 1.0])
Sigma = np.array([[4.0, 1.0],
[1.0, 1.0]])
samples = rng.multivariate_normal(mu, Sigma, size=n)
def plot_ellipse(ax, mu, Sigma, n_std=2, **kwargs):
vals, vecs = eigh(Sigma)
theta = np.linspace(0, 2*np.pi, 200)
circle = np.array([np.cos(theta), np.sin(theta)])
ellipse = (vecs @ np.diag(np.sqrt(vals) * n_std)) @ circle + mu[:, None]
ax.plot(ellipse[0], ellipse[1], **kwargs)
fig, axes = plt.subplots(1, 3, figsize=(14, 4.5))
ax = axes[0]
ax.scatter(samples[:800, 0], samples[:800, 1], alpha=0.3, s=5)
plot_ellipse(ax, mu, Sigma, n_std=1, color="tab:red", linewidth=2, label="1σ")
plot_ellipse(ax, mu, Sigma, n_std=2, color="tab:red", linewidth=1.5, linestyle="--", label="2σ")
ax.scatter(*mu, color="black", marker="x", s=80, label="μ")
ax.set_aspect("equal")
ax.set_xlabel("X₁"); ax.set_ylabel("X₂")
ax.set_title("Scatter + level sets")
ax.legend()
ax = axes[1]
cond_val = 3.0
near = samples[np.abs(samples[:, 0] - cond_val) < 0.2]
ax.hist(near[:, 1], bins=30, density=True, alpha=0.7, label=f"X₂ | X₁≈ {cond_val}")
# True conditional: X₂ | X₁ = x₁
rho = Sigma[0, 1] / np.sqrt(Sigma[0, 0] * Sigma[1, 1])
cond_mean = mu[1] + rho * np.sqrt(Sigma[1, 1] / Sigma[0, 0]) * (cond_val - mu[0])
cond_var = Sigma[1, 1] * (1 - rho**2)
x2_grid = np.linspace(mu[1] - 3, mu[1] + 3, 200)
cond_pdf = (1 / np.sqrt(2 * np.pi * cond_var)) * np.exp(-0.5 * (x2_grid - cond_mean)**2 / cond_var)
ax.plot(x2_grid, cond_pdf, "tab:red", linewidth=2, label="True conditional")
ax.set_title(f"Conditional X₂ | X₁ = {cond_val}")
ax.set_xlabel("X₂"); ax.legend()
ax = axes[2]
x1_marginal = np.linspace(mu[0] - 4, mu[0] + 4, 200)
marg_pdf = (1 / np.sqrt(2 * np.pi * Sigma[0, 0])) * np.exp(-0.5 * (x1_marginal - mu[0])**2 / Sigma[0, 0])
ax.hist(samples[:, 0], bins=50, density=True, alpha=0.5, label="Empirical marginal")
ax.plot(x1_marginal, marg_pdf, "tab:blue", linewidth=2, label="True marginal")
ax.set_title("Marginal X₁")
ax.set_xlabel("X₁"); ax.legend()
plt.tight_layout()
plt.show()
print(f"Sample mean: {samples.mean(axis=0)}")
print(f"Sample cov:\n{np.cov(samples.T)}")
print(f"Conditional X₂ | X₁=3: mean={cond_mean:.3f}, var={cond_var:.3f}")