Back to Blog

Math — Multivariate Probability

·Reha Tuncer·Math
View source on GitHub

Math — Multivariate Probability

A progressive implementation of multivariate statistics — from mean vectors and covariance matrices to correlation and the multivariate normal distribution, building toward the Gaussian foundations of machine learning with NumPy.


Learning Objectives

#Concept
1Compute the mean vector of a multivariate dataset with np.mean and axis control
2Compute the covariance matrix manually using the sample covariance formula (no np.cov)
3Understand Bessel's correction (n1n-1n1) for an unbiased sample covariance estimate
4Derive the correlation matrix from covariance via diagonal scaling
5Fit a multivariate normal distribution from data using maximum likelihood estimation
6Compute the multivariate normal PDF using the full formula with determinant and inverse
7Validate inputs with cascading exception checks in a specific priority order

Data Conventions

This module uses two matrix layouts — a key learning point about data conventions in ML:

LayoutShapeMeaningUsed In
Samples × Features(n,d)(n, d)(n,d)nnn data points, ddd dimensions — each row is a sampleTask 0, Task 1
Features × Samples(d,n)(d, n)(d,n)ddd dimensions, nnn data points — each column is a sampleMultiNormal class

The transpose flips between conventions. Pay attention to which axis you compute the mean along and how the covariance matrix multiplication is ordered.


Task-by-Task Reference

Each task below highlights the unique challenge it posed and the new technique introduced — techniques from earlier tasks are not repeated.


Task 0 — Mean & Covariance (0-mean_cov.py)

Challenge: Compute both the mean vector and covariance matrix of a multivariate dataset XXX — implementing the sample covariance formula from scratch without using np.cov.

Approach: Given XXX of shape (n,d)(n, d)(n,d), compute the mean with np.mean(X, axis=0, keepdims=True) to get shape (1,d)(1, d)(1,d). Center the data: XμX - \muXμ. The sample covariance is 1n1(Xμ)(Xμ)\frac{1}{n-1} (X - \mu)^\top (X - \mu)n11(Xμ)(Xμ) — the matrix multiplication of the centered data's transpose with itself, scaled by Bessel's correction. Inputs are validated in order: 2D ndarray check → n2n \ge 2n2 check.

New techniques introduced:

TechniquePurpose
np.mean(X, axis=0, keepdims=True)Compute mean along samples axis, preserving 2D shape (1,d)(1, d)(1,d)
Data centering: XμX - \muXμSubtract the mean from every row via NumPy broadcasting
`(X - \mu)^\top @ (X - \mu) / (n - 1)$Sample covariance as sum of outer products divided by degrees of freedom
Bessel's correction (n1n-1n1 denominator)Unbiased estimate — sample covariance, not population
isinstance(X, np.ndarray) and X.ndim != 2Validate 2D array before any computation
n < 2ValueErrorRequire multiple data points for meaningful covariance

Key takeaway: The covariance matrix Σ\SigmaΣ captures how each pair of dimensions varies together — Σij\Sigma_{ij}Σij is the covariance between dimension iii and dimension jjj. Bessel's correction (n1n-1n1) gives an unbiased estimate of the population covariance. Without keepdims=True, the mean collapses to 1D, breaking the broadcasting in the centering step.


Task 1 — Correlation Matrix (1-correlation.py)

Challenge: Convert a covariance matrix into a correlation matrix — normalizing covariances to the [1,1][-1, 1][1,1] range so relationships between variables measured in different units become directly comparable.

Approach: Extract the diagonal variances σi2\sigma_i^2σi2 with np.diagonal(). Compute scaling factors σi1/2\sigma_i^{-1/2}σi1/2 (element-wise power). Build a diagonal matrix DDD from these factors with np.diagflat(). The correlation matrix is the sandwich product DCDD \cdot C \cdot DDCD, which scales each covariance σij\sigma_{ij}σij by 1σiiσjj\frac{1}{\sqrt{\sigma_{ii} \cdot \sigma_{jj}}}σiiσjj1.

New techniques introduced:

TechniquePurpose
np.diagonal(C)Extract the variance vector (diagonal of covariance matrix)
diag ** (-1/2)Element-wise power — compute 1/σi21/\sqrt{\sigma_i^2}1/σi2 for each variance
np.diagflat(scaling_factors)Build a diagonal matrix from a 1D array of scaling factors
DCDD \cdot C \cdot DDCD sandwich productNormalize every (i,j)(i,j)(i,j) entry: ρij=σijσiiσjj\rho_{ij} = \frac{\sigma_{ij}}{\sqrt{\sigma_{ii} \cdot \sigma_{jj}}}ρij=σiiσjjσij
Correlation always in [1,1][-1, 1][1,1]Standardized covariance — scale-invariant and unit-free

Key takeaway: Correlation is standardized covariance — it strips away the units so you can compare relationships across variables measured on different scales (e.g., height in cm vs. weight in kg). The diagonal scaling trick DCDDCDDCD is a clean one-liner that transforms any covariance matrix into its correlation form.


Task (class) — Multivariate Normal Distribution (multinormal.py)

Challenge: Implement a class that fits a multivariate normal distribution from data and computes the PDF for any point — combining mean, covariance, determinant, and inverse into the full multivariate Gaussian formula. This is the culmination of all multivariate probability concepts.

Approach: The constructor accepts data of shape (d,n)(d, n)(d,n) (features × samples — note the transposed convention from Task 0). It computes the mean along axis 1 (per-feature) with keepdims=True for shape (d,1)(d, 1)(d,1). The covariance is 1n1(Xμ)(Xμ)\frac{1}{n-1} (X - \mu)(X - \mu)^\topn11(Xμ)(Xμ) — note the reversed multiplication order vs. Task 0 because of the transposed layout. The pdf(x) method computes the full multivariate normal density:

f(x)=(2π)d/2Σ1/2exp ⁣(12(xμ)Σ1(xμ))f(x) = (2\pi)^{-d/2} \, |\Sigma|^{-1/2} \, \exp\!\left(-\frac{1}{2}(x - \mu)^\top \Sigma^{-1} (x - \mu)\right)f(x)=(2π)d/2∣Σ1/2exp(21(xμ)Σ1(xμ))

using np.linalg.det() for the determinant, np.linalg.inv() for the precision matrix, and .item() to extract the scalar result from the 1×1 matrix.

New techniques introduced:

TechniquePurpose
Class-based distribution modelingEncapsulate parameters (mean, cov) and operations (pdf) in a reusable object
(d,n)(d, n)(d,n) data conventionFeatures as rows, samples as columns — common in ML literature
np.mean(data, axis=1, keepdims=True)Compute per-feature means, yielding shape (d,1)(d, 1)(d,1)
(Xμ)@(Xμ)(X - \mu) @ (X - \mu)^\top(Xμ)@(Xμ) for covarianceCorrect multiplication order for (d,n)(d, n)(d,n) layout
np.linalg.det(self.cov)Determinant $
np.linalg.inv(self.cov)Precision matrix Σ1\Sigma^{-1}Σ1 — used in the Mahalanobis distance
(xμ)Σ1(xμ)(x - \mu)^\top \Sigma^{-1} (x - \mu)(xμ)Σ1(xμ)Mahalanobis distance — "how many std devs away" accounting for correlations
.item() on 1×1 arrayExtract a Python float from a NumPy array of shape (1,1)(1, 1)(1,1)
(2π)d/2(2\pi)^{-d/2}(2π)d/2 normalization factorEnsures the PDF integrates to 1 over Rd\mathbb{R}^dRd

Key takeaway: The multivariate normal PDF generalizes the 1D Gaussian bell curve to ddd dimensions. The covariance matrix Σ\SigmaΣ controls the shape (spread) and orientation (correlation) of the bell. The Mahalanobis distance (xμ)Σ1(xμ)(x - \mu)^\top \Sigma^{-1} (x - \mu)(xμ)Σ1(xμ) inside the exponent measures distance accounting for correlations — points on the same density contour have the same Mahalanobis distance. The determinant Σ|\Sigma|∣Σ∣ in the normalization scales the peak height: larger determinant → more spread → lower peak.


Technique Inventory

TaskNew technique summarizedCategory
0np.mean with axis/keepdims, data centering, Bessel's correction (n1)(n-1)(n1), covariance via (Xμ)(Xμ)(X-\mu)^\top(X-\mu)(Xμ)(Xμ)Mean & Covariance
1np.diagonal(), np.diagflat(), DCDDCDDCD sandwich, correlation = covariance ÷ (std × std)Correlation
classClass-based distribution, (d,n)(d,n)(d,n) layout, np.linalg.det/inv, Mahalanobis distance, multivariate PDF formulaMultivariate Normal

Multivariate Probability Pipeline

Data X ──→ Mean μ ──→ Covariance Σ ──→ Correlation P ──→ MultiNormal(μ, Σ) ──→ PDF(x)
  (n×d)    (1×d)        (d×d)            (d×d)              class               scalar
  1. Mean locates the center of the data in ddd-dimensional space
  2. Covariance captures the spread and pairwise relationships
  3. Correlation standardizes to [1,1][-1, 1][1,1] for interpretability
  4. MultiNormal packages mean and covariance into a full probability distribution
  5. PDF answers: "how likely is this point under the fitted distribution?"

Resources