Machine Learning: Unsupervised Learning
Unsupervised methods are harder to audit than supervised ones for a simple reason: there is no held-out label to be wrong against. A clustering always returns clusters, an embedding always returns a picture, and a low-rank approximation always returns a matrix — so the question is never whether the method ran but whether the structure it reports is in the data or in the algorithm.
That makes the diagnostics the substance rather than the garnish. A rank-k reconstruction has to be compared against the right object, and against a baseline; a cluster count has to survive resampling before it means anything; an embedding's apparent groups have to be checked against what the distances actually preserve. Each example here is built around the check as much as the method.
The finance thread runs through all four: the same 48-stock cross-section and volatility series used elsewhere in the collection, so what these methods find can be set against what the supervised and Bayesian treatments found on identical data.
Two different jobs, both called unsupervised. The four examples split cleanly and the split is worth having in mind, because the methods are not alternatives to each other. The first groups observations: given 3,459 trading days, decide which of them belong together. The other three compress features: given 48 stocks measured every week, find a handful of numbers that carry most of what all 48 were doing. Grouping rows, compressing columns. A clustering answers “which days are alike?”; a decomposition answers “what are these 48 series really made of?” The reason they sit together is the shared difficulty rather than a shared technique — in both cases the method returns an answer whether or not one exists, and no held-out label is available to say which.
Grouping: centroids, mixtures, and a fitting procedure that can settle in the wrong place. k-means picks k centres, assigns every point to its nearest, moves each centre to the mean of what it caught, and repeats. Assignments are hard — a point belongs to exactly one cluster — and because distance to a centre is the only criterion, the clusters it can express are effectively spherical and similar in size. A Gaussian mixture relaxes both: each cluster gets a full mean and covariance, so it can be elongated and tilted, and assignments become soft, a probability of membership rather than a verdict. It is fitted by EM (expectation–maximisation), which alternates between computing those membership probabilities and re-estimating each cluster from the points weighted by them. EM is a local optimiser: it climbs to a nearby peak of the likelihood, and different starting points reach different peaks. That is why the from-scratch and reference implementations here agree on the likelihood to four figures and still disagree about which days belong to which cluster.
How many clusters — three answers that need not agree. Nothing in either algorithm chooses k; it is supplied. Three ways to choose it recur. The elbow plots the within-cluster spread against k and looks for where the curve stops falling steeply, the point past which extra clusters stop buying much. BIC — the Bayesian information criterion — scores a fitted model as its likelihood minus a penalty that grows with the number of parameters and with the amount of data, so it rewards fit while charging for complexity, and the k that minimises it is preferred. Both of those are computed on the same data the model was fitted to. The third is stability, which asks a different question entirely: refit the whole thing on two overlapping subsamples and check whether the days both fits saw are grouped the same way. Agreement is scored by the adjusted Rand index (ARI), which counts the pairs of points that two partitions agree to put together or apart, corrected so that chance agreement scores 0 and an identical partition scores 1. A cluster count that cannot reproduce itself on a resample is a property of the fit rather than of the data.
Compressing: components, loadings, and what is left over. PCA (principal component analysis) finds the direction along which the data varies most, then the next such direction at right angles to it, and so on — rewriting the data in a new set of axes ordered by how much variation each accounts for. That share is the explained-variance ratio, and it is what makes the compression measurable: if the first three axes carry 56% of the variation, the other 45 carry the rest between them. Each component is defined by its loadings, the weights it puts on the original variables, and those weights are readable — a component with all-positive loadings on 48 stocks is a market factor, one that is positive on energy and negative on technology is a sector bet. The computation is the SVD (singular value decomposition), a matrix factorisation that produces all of this in one step. Factor analysis looks similar and asks a different question: instead of finding directions of maximum variance, it models each variable as a few shared factors plus a term unique to that variable, which splits every stock's risk into a systematic part moving with everything else and an idiosyncratic part that diversifies away. PCA blurs that distinction; factor analysis is built on it.
Learned and nonlinear: bottlenecks and manifolds. An autoencoder is a network trained to reproduce its own input after forcing it through a narrow middle layer — the bottleneck. Whatever survives that squeeze is the latent code, and because the network is penalised for a poor reconstruction, the code has to retain whatever matters most. With no nonlinearities this is PCA in disguise, recovering the same subspace though not the same axes; with them it can follow a curved surface rather than a flat one. That curved surface is the manifold — the idea that data described by 784 pixel values may in truth vary along only a few dozen meaningful directions, which need not be straight lines. The gap between the linear and nonlinear versions is what measures whether curvature was worth the trouble.
Embeddings, and the circular scoring problem. t-SNE (t-distributed stochastic neighbour embedding) and UMAP (uniform manifold approximation and projection) exist to put high-dimensional data on a page for a human to look at. t-SNE turns distances into probabilities of being neighbours in both the original and the 2-D space, then moves the 2-D points until those two distributions match, measured by the Kullback–Leibler divergence — a non-symmetric measure of how far one probability distribution sits from another. UMAP builds a graph of nearest neighbours and lays it out to preserve that graph. Scoring the result is where the trap is. Silhouette asks how tight and well-separated the clusters look in the picture, which is precisely what both methods optimise — so it rewards the algorithm for succeeding at its own objective, whether or not the groups are real. The honest measures ask about fidelity to the original space instead: trustworthiness (are the points that ended up adjacent genuinely neighbours in the original data?), the share of each point's high-dimensional neighbours that survive the projection, and reading a held-out label off the map with a nearest-neighbour classifier. Spearman rank correlation, used here to check whether coarse arrangement is preserved, compares two orderings rather than two sets of values, so it registers whether distant pairs stayed distant without demanding the distances themselves be reproduced.
Four methods, one problem: the check is the result
Every value is committed notebook output. Each panel carries its own measure and its own axis — an adjusted Rand index, a mean absolute correlation, a percentile and a silhouette are not comparable quantities and are not plotted as though they were.
A is the shape of the whole section. Two standard criteria disagree — the elbow says three clusters, BIC says seven — and neither can win the argument, because both are computed on the same data the model was fitted to. A criterion that asks something else entirely settles it: refit on overlapping subsamples and see whether the days get grouped the same way. Everything above five collapses, the mixture falling to 0.45–0.57, meaning those extra components land somewhere different every time they are fitted. And the control explains the overshoot rather than merely noting it: a single simulated fat-tailed population, with no regimes in it whatsoever, asks BIC for three components purely to fit its tails — while a Gaussian control correctly asks for one. A mixture will spend components on non-Gaussian shape, and daily equity returns are famously fat-tailed.
B is the one that would fool almost anyone, because the wrong answer is the flattering one. To show a correlation matrix is nearly low-rank, the tempting move is to rebuild the data from k components and correlate the result. Do that at rank 1 and every pair of stocks reads 1.000 — apparently a perfect reconstruction, actually an artefact: a rank-1 matrix has one independent direction, and correlating it rescales every column by its own reconstructed spread, so the correlations are pushed toward ±1 no matter how bad the fit. Note the direction of the error. The rebuild reports more correlation than the data contains (0.699 against 0.375 at rank 3), so the check does not merely fail, it fails in the direction that confirms what it was run to confirm. Truncating the correlation matrix itself gives the honest figure: 19.5% relative error at rank 3, 12.2% on the off-diagonal entries. Real structure — three numbers per stock carry most of a 48×48 matrix — stated at its real size.
C is the same lesson arriving twice more from different directions. On the left, an anomaly detector with 1,748 parameters and 312 weeks to fit rates the COVID crash at the 5.8th percentile of unusualness — among the most ordinary weeks in the sample. Scored on folds it was not fitted to, the same week is the 99.7th. The network had memorised its own outliers, so the detector inverted precisely where it was supposed to work; a plain rank-4 PCA baseline, which cannot memorise, was right all along at 99.4. On the right, 2,000 points of pure isotropic noise — no structure of any kind — embed into a picture of well-separated islands scoring 0.306 and 0.334, against 0.152 for the genuine ten-class structure of Fashion-MNIST. Roughly twice the score for none of the structure. In 50 dimensions the same noise correctly scores 0.014, so the clusters are not being found, they are being made — and no amount of looking at the picture would reveal it.
How the four examples relate
Two different jobs, and a build order. Grouping observations comes first; then three ways of compressing features, each generalising the one before it.
Grouping the rows
Which observations belong together, and how would you know?
1 · Clustering — k-means & Gaussian mixturesmarket regimes found without labels — and three criteria for k that do not agreeCompressing the columns
The same 48-stock cross-section, compressed three ways in increasing generality.
2 · PCA, SVD & factor analysisthe linear answer — the market factor recovered from the data, and the low-rank claim stated honestly 3 · Autoencodersthe nonlinear generalisation — a linear one collapses back onto PCA exactly 4 · t-SNE & UMAPcompression for the eye rather than for reuse — and what those pictures cannot tell youThe ladder in the second column is worth reading as one argument. PCA finds the best flat subspace; an autoencoder with no nonlinearities provably finds the same one, which is the anchor that makes the comparison meaningful; adding nonlinearities lets it curve, and the gain is measurable (14% lower test error at the same bottleneck). t-SNE and UMAP then abandon reuse altogether for legibility. Each step buys something and gives something up, and the last step gives up the most: an embedding cannot be inverted, cannot be applied to new points in t-SNE's case, and — as panel C shows — cannot be trusted on the evidence of the picture alone.
Clustering — k-means, Gaussian Mixtures & Market Regimes
k-means and a full-covariance Gaussian mixture built from scratch and validated against scikit-learn — on the partition as well as the fit, which come apart: the two 3-cluster labelings agree at ARI 0.896, not 1.000, because EM is a local optimiser. The number of regimes is then contested rather than asserted. The elbow says three, BIC says seven, and both are in-sample measures. Resampling settles it from the other end: everything above five fails to reproduce — BIC’s answer scores 0.57 — and the elbow picks three from what survives. A control shows why BIC overshoots: a single simulated fat-tailed population with no regimes in it asks for three components purely to fit its tails. The three regimes that survive are calm, sell-off and rebound — the two turbulent ones at the same volatility but 76% against 1% down days — dating 2008, 2002 and 2009 with no labels supplied.
View example →PCA, SVD & Factor Analysis — the Cross-Section’s Factors
PCA built from scratch via the SVD and matched to scikit-learn, then turned on 48 stocks to recover the market factor from the data alone: PC1 explains 40% of the covariation, its loadings are all one sign, and its return correlates 0.998 with the equal-weight index — the market rediscovered with no index supplied. Higher components are mixed-sign long/short style portfolios (PC2 goes long energy, short tech). The low-rank claim is then made carefully, because the tempting construction is wrong: correlating a rank-k rebuild of the data rescales every column by its own reconstructed spread and drives correlations toward ±1 — at rank 1 every pair reads exactly 1.000. The spectral truncation of the correlation matrix itself gives 19.5% error at rank 3, 12.2% off-diagonal: real structure, stated at its real size. Factor analysis then splits each stock into systematic and diversifiable variance — 53% systematic on average — the distinction PCA blurs.
View example →Autoencoders — Nonlinear Compression & the In-Sample Anomaly Trap
The linear anchor stated precisely: a linear autoencoder recovers PCA’s subspace — principal angles of 0.000° — but not its axes, because nothing in a squared-error loss prefers one basis of that subspace to another. Nonlinearity then earns its keep, 14% lower test error than PCA at the same 32-dimensional bottleneck on Fashion-MNIST, and a 2-D latent space that reads out class labels at 0.673 against PCA’s 0.525 — scored, not eyeballed. The anomaly application then walks into the trap deliberately: a 1,748-parameter network scored on the 312 weeks it was fitted to memorises its own outliers, rating the COVID crash at the 6th percentile of reconstruction error. Held out, the same week is the 99.7th. The two rankings share none of their top five, and done properly the detector tracks a rank-4 PCA baseline at 0.91.
View example →t-SNE & UMAP — Manifold Learning, and What These Plots Cannot Tell You
The two embeddings compared against PCA on Fashion-MNIST, scored with measures that do not simply reward the compact geometry these methods are built to produce: 0.766 and 0.750 nearest-neighbour accuracy against PCA’s 0.520, keeping three to four times as much of each point’s 50-D neighbourhood. Then the control the usual caveats only describe: 2,000 points of pure isotropic noise, with no structure of any kind, embed into a picture of well-separated islands that scores 0.31 and 0.33 by silhouette — roughly twice what the genuine ten-class structure scores. The two claims habitually used to prefer UMAP are measured rather than repeated, and neither holds at this scale: t-SNE is faster at every size tried, and preserves global geometry better (+0.695 against +0.598). A UMAP sector map of 48 stocks closes it, bounded honestly against the raw return space that already contains the structure.
View example →