SafeZone AI Learn
Learn/ Machine Learning/ Unsupervised Learning · lesson 2 of 7

Gaussian mixtures and EM

Clustering restated as maximum likelihood on a latent-variable model: responsibilities, the EM algorithm derived via Jensen's inequality, its monotonicity guarantee watched live — and k-means unmasked as a frozen special case.

k-means answers “which cluster?” with a hard label and describes every cluster as a point. Both simplifications cost information: boundary points get confident labels they don’t deserve, and elongated clusters get described by a center that captures nothing of their shape. The fix is to do what this curriculum always does when a procedure feels ad hoc — write down the probabilistic model the procedure is secretly assuming, then do maximum likelihood properly. The model is the Gaussian mixture; the algorithm that maximizes it is EM, the most important algorithm in classical unsupervised learning and the conceptual ancestor of variational autoencoders.

The model: data with a latent label

Assume each point was generated by a two-stage story: first draw a hidden component zi{1..k}z_i \in \{1..k\} with probabilities π1,,πk\pi_1, \ldots, \pi_k; then draw the point from that component’s Gaussian:

p(x)  =  j=1kπjN(xμj,Σj).p(x) \;=\; \sum_{j=1}^{k} \pi_j \, \mathcal{N}(x \mid \mu_j, \Sigma_j).

Clustering becomes inference of the latent zz, and Bayes’ theorem (lesson 4 of Probability) gives the exact answer — the responsibility of component jj for point ii:

rij  =  p(zi=jxi)  =  πjN(xiμj,Σj)lπlN(xiμl,Σl).r_{ij} \;=\; p(z_i = j \mid x_i) \;=\; \frac{\pi_j \, \mathcal{N}(x_i \mid \mu_j, \Sigma_j)} {\sum_{l} \pi_l \, \mathcal{N}(x_i \mid \mu_l, \Sigma_l)} .

Soft labels, with calibrated uncertainty at the boundaries — and full covariances Σj\Sigma_j, so clusters can be elongated, tilted, and different sizes. Everything k-means couldn’t say.

EM: maximum likelihood when a variable is missing

Direct MLE on logp(x)=logj()\log p(x) = \log \sum_j (\cdots) is awkward — the sum sits inside the log. EM’s move: lower-bound the log-likelihood using Jensen’s inequality with any distribution qq over the latent labels,

logp(xθ)    Eq(z)[logp(x,zθ)]+H(q)  =:  L(q,θ),\log p(x \mid \theta) \;\ge\; \mathbb{E}_{q(z)}\big[\log p(x, z \mid \theta)\big] + H(q) \;=:\; \mathcal{L}(q, \theta),

then alternate: the E-step sets q(z)=p(zx,θ)q(z) = p(z \mid x, \theta) — the responsibilities — which makes the bound tight; the M-step maximizes the bound over θ\theta, which has closed form because the log now sits inside the expectation:

πj=Njn,μj=1Njirijxi,Σj=1Njirij(xiμj)(xiμj),\pi_j = \frac{N_j}{n}, \qquad \mu_j = \frac{1}{N_j}\sum_i r_{ij}\, x_i, \qquad \Sigma_j = \frac{1}{N_j}\sum_i r_{ij}\,(x_i - \mu_j)(x_i - \mu_j)^\top,

with Nj=irijN_j = \sum_i r_{ij} the “effective count”. These are exactly the ordinary Gaussian MLEs from the Probability module, with each point counted fractionally by responsibility. Tight bound + maximized bound ⟹ the log-likelihood never decreases — EM’s celebrated monotonicity, and the number the widget audits every step:

On the anisotropic blobs — precisely where k-means’ spherical assumption dies — run EM ×10 and watch the ellipses rotate and stretch onto the elongated clusters, something no centroid can express. The sparkline is the monotonicity theorem holding in public: every step up or flat, never down. Boundary points render translucent — that is a responsibility near 0.5, an honest “not sure” no hard clusterer can utter. Re-initialize a few times: like Lloyd’s, EM finds LOCAL optima; and on the moons it fails exactly as k-means did, because a moon is not a Gaussian either — a reminder that upgrading the machinery does not upgrade a wrong model class.

k-means is a frozen mixture

Fix every Σj=σ2I\Sigma_j = \sigma^2 I and take σ0\sigma \to 0: responsibilities collapse to one-hot (nearest center wins), the M-step becomes the plain mean, and EM becomes Lloyd’s algorithm — k-means is the zero-temperature limit of a spherical Gaussian mixture. This is why k-means implicitly assumes round, equal clusters: it is doing MLE in a model that asserts them. The pattern — “popular heuristic = probabilistic model + degenerate limit” — recurs across ML, and knowing the model tells you exactly which dial you froze.

The fine print, all of it load-bearing

  • Singularities. The likelihood is unbounded: park a component on a single point and shrink its variance, and logp\log p \to \infty. Real implementations add a covariance floor or a prior (MAP-EM) — the widget adds a small ridge, the Bayesian lesson’s medicine again.
  • Choosing k, again — but now likelihood-based tools exist: BIC (2logL^+plogn-2\log\hat L + p\log n) and its kin penalize the extra parameters each component costs. Better grounded than the elbow, still not oracle.
  • Covariance budgets. Full Σj\Sigma_j costs O(kd2)O(kd^2) parameters — in high dimensions you tie covariances, make them diagonal, or go spherical: a bias–variance dial identical in spirit to regularization.
  • Identifiability. Components can be permuted freely (“label switching”), which is harmless for clustering, treacherous for interpreting “component 2” across runs.
  • EM beyond mixtures. The same E/M scaffolding fits hidden Markov models (the Forecasting track’s state-space cousins), factor analysis, and — with qq restricted to a tractable family instead of made exact — becomes variational inference, the engine of VAEs in the Deep Learning track. The bound L(q,θ)\mathcal{L}(q,\theta) you met here is the ELBO you will meet there.
import numpy as np
from sklearn.mixture import GaussianMixture
from sklearn.datasets import make_blobs

X, _ = make_blobs(n_samples=400, centers=3, random_state=2)
X = X @ np.array([[1.4, 0.7], [0.0, 0.4]])          # tilt: break sphericity

gm = GaussianMixture(n_components=3, covariance_type="full", random_state=0).fit(X)
r = gm.predict_proba(X)                              # responsibilities
print(gm.lower_bound_)                               # avg log-lik at convergence
print(r.max(axis=1).min())                           # least-confident point
print(gm.bic(X), GaussianMixture(6, random_state=0).fit(X).bic(X))  # k by BIC

Exercises

Work these before the next lesson

  1. Derive the M-step for μj\mu_j: differentiate irijlogN(xiμj,Σj)\sum_i r_{ij} \log \mathcal{N}(x_i \mid \mu_j, \Sigma_j) and confirm the responsibility-weighted mean. Where exactly does the E-step’s “freeze rr” matter for this to be valid?
    Solution

    Worked solutions are part of Premiumunlock all of them for £5/month →

  2. 5 more exercises — each with a worked solution — are part of Premium. Unlock everything for £5/month →

References

  • A. Dempster, N. Laird & D. Rubin, “Maximum Likelihood from Incomplete Data via the EM Algorithm”, JRSS-B 1977.
  • C. Bishop, Pattern Recognition and Machine Learning, ch. 9 — mixtures and EM at exactly this depth, with the k-means limit.
  • R. Neal & G. Hinton, “A View of the EM Algorithm that Justifies Incremental, Sparse, and Other Variants”, 1998 — the bound-maximization view used here.