Gaussian Mixture Models and Expectation-Maximization › Visualizing Gaussian Mixture Models

Michael BrenndoerferOctober 29, 20268 min read
Machine Learning from ScratchAll chapters
Part 9 of 15Unsupervised Learning
Chapter 66Gaussian Mixture Models and Expectation-Maximization › Visualizing Gaussian Mixture Models
Reading section 7 of 10 · Visualizing Gaussian Mixture Models · 8 minSection 7 of 10 · 8 min

Section 7 of 10 · 8 min read

Gaussian Mixture Models and Expectation-Maximization › Visualizing Gaussian Mixture ModelsSection view · Sections in this chapter7 / 10 ↓
Reading tools Definitions, links & notes

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Notes & comments

We begin with the data as generated, coloured by the true component. In a real problem those colours would be unavailable (the whole difficulty is that they are), but seeing them establishes what the model is trying to recover.

VisualizationOut [16]
CollapseExpand
Scatter plot of two clusters on a plane, the first a wide tilted ellipse running lower-left to upper-right, the second a smaller tilted ellipse overlapping it.
Four hundred observations drawn from two Gaussian components with different weights, sizes, and orientations. Colours show the generating component, which is unobserved in practice; the two clouds overlap in the middle with axes pointing in different directions.

The two clouds overlap in the middle and their axes point in different directions, so no single distance threshold separates them cleanly. A circular cluster boundary is visibly the wrong shape for either cloud.

The fitted model replaces the truth with a density. The contours below show the total mixture density; the dashed contours show how each component alone would be shaped.

PythonIn [17]
CollapseExpand
xx, yy = np.meshgrid(np.linspace(x_lo, x_hi, 300), np.linspace(y_lo, y_hi, 300))
grid = np.column_stack([xx.ravel(), yy.ravel()])
log_joint_grid = log_component_density(
    grid, model["weights"], model["means"], model["covs"], model["reg_covar"]
)
dens = np.exp(logsumexp(log_joint_grid, axis=1)).reshape(xx.shape)
levels = np.exp(
    np.linspace(np.log(dens.max() * 0.02), np.log(dens.max() * 0.9), 8)
)
VisualizationOut [18]
CollapseExpand
Scatter plot with grey density contours overlaid, plus two dashed ellipses of different orientations centred on two marked means.
Fitted two-component mixture. Muted contours show the total density, dashed ellipses mark one standard deviation of each component, and crosses mark the fitted means. The ellipses capture the differing orientation and aspect ratio of each component's covariance.

Each dashed ellipse is a radius-one Mahalanobis contour, not a universal 68% probability region. In two dimensions it encloses about 39% of its Gaussian component's probability. It has the orientation and aspect ratio of that component's covariance matrix: one is long and tilted steeply, the other is rounder and tilted the other way. Those shapes are estimated from the data, not supplied, and they are what a diagonal or spherical covariance type would be unable to represent.

The real output of the fit is not the contours but the responsibilities. Colouring each point by its posterior probability of belonging to component 1 produces a gradual transition through the overlap region instead of a step.

VisualizationOut [19]
CollapseExpand
Scatter plot where points are coloured on a continuous scale from blue to red according to the posterior probability of the first component.
Posterior probability of component 1 for each observation, with points coloured on a continuous scale from low to high responsibility. Points in the overlap region fade between the two components rather than being assigned to one, and the colour gradient is broad around the overlap. Observations strongly favoured by either component have saturated colours.

The colour gradient is broad around the overlap, while observations strongly favoured by either component have saturated colours. Points in the pale region have ambiguous component assignments under this fitted model; a downstream decision that treats them as firmly assigned is throwing away information the model has already computed.

K-means, fitted to the same data, has no such region. It produces a boundary and commits.

VisualizationOut [20]
CollapseExpand
Scatter plot of the same data with points coloured in two solid colours by k-means cluster label.
Hard assignments from k-means on the same data, with every point fully assigned by colour. Points the mixture model places near a responsibility of one half are forced into a cluster, and the nearest-centroid rule cuts through the overlap with a straight decision boundary.

Comparing this with the previous figure shows where the two methods diverge: near the interface, k-means draws a straight line through points that the mixture model declines to commit on. The pictures summarize different fitted models. The mixture displays its conditional uncertainty; its visual smoothness does not establish that the model is correct.

Finally, inspect the optimization itself. This seeded run records increasing log-likelihood values that flatten; we check that observed behaviour rather than assuming it from the diagonal-addition update.

VisualizationOut [21]
CollapseExpand
Line chart of log-likelihood against EM iteration, increasing and then levelling off.
Log-likelihood recorded at each EM iteration for the fitted two-component mixture. The displayed run rises and flattens; the flat right-hand end is the practical stopping signal, but it does not show whether this plateau is the highest one available.

The exact EM proof explains why likelihood monitoring matters. Here diagonal regularization means we must also check for decreases; a flat right-hand end is a practical stopping signal. Note what the curve does not show: whether this plateau is the highest one available.

Different starting points give a practical check on that question, although finitely many starts cannot settle it. The figure below runs the same algorithm from five random initializations and overlays the trajectories.

PythonIn [22]
CollapseExpand
random_runs = [
    fit_gmm(X, 2, init="random", seed=s, reg_covar=1e-6) for s in range(5)
]
VisualizationOut [23]
CollapseExpand
Five line charts of log-likelihood against iteration, rising and flattening at different final heights.
Five independent EM runs from random initializations on the same data, with final log-likelihoods reported in the legend. Different final heights show initialization dependence under this stopping rule; they do not by themselves certify stationary points or a global optimum.

The legend reports each run's final log-likelihood. Where the converged curves separate, the lower plateaus are poorer fitted solutions. The finite trajectories do not establish whether a plateau is an exact local optimum. When the curves do coincide, the data happened to be forgiving, and nothing in the algorithm guarantees that it will stay that way. This is the practical argument for n_init.

Comments

Add to the conversation

A question, a correction, or an example from your own work.

No comments yet. Be the first to share your thoughts!

Newsletter

Stay up to date

Get new articles, book updates, and notes on AI and technology.

Unsubscribe at any time. Privacy policy