Core machine learning

Part 7 of 8 in Core machine learning

Clustering when nobody labelled anything

k-means run by hand on eight numbers, why its score always improves when you ask for more clusters, and two shapes of data where it returns a confident answer that is the wrong grouping.

Nine thousand images of metal surfaces, none of them labelled, and a question from the plant manager that sounds simple: how many kinds of defect are we actually producing. Clustering is the family of methods that appears to answer it, and the appearance is the problem, because every one of them returns an answer whether or not there is anything there to find.

The 340 labelled images in Support vector machines and the margin told the team what a defect looked like once somebody had already decided it was one. These nine thousand come with no such decision attached, and no score exists that says whether the grouping produced is right. k-means is the method that gets used anyway, so it is the one worth being able to run in your head.

Eight numbers, run to convergence

Average order value for eight customer accounts, in hundreds: 2, 3, 4, 10, 11, 12, 30, 31.

Ask for two clusters. k-means needs starting centres, so take the two worst available, 2 and 3, and watch it recover.

Assign. Each value joins the nearer centre. Only the value 2 is nearer to 2. Everything else is nearer to 3.

Update. Each centre moves to the mean of its members. The first stays at 2. The second becomes the mean of 3, 4, 10, 11, 12, 30 and 31, which is 101 divided by 7, or 14.43.

Assign again. Now 3 and 4 are nearer to 2 than to 14.43. The centres become 3 and the mean of 10, 11, 12, 30, 31, which is 18.8.

Again. With centres at 3 and 18.8, the value 10 is 7 from the first and 8.8 from the second, so it switches sides. Centres become 4.75 and 21.

Again. At those centres, 11 and 12 switch too. Centres become 7 and 30.5.

Again. Nothing moves. The answer is the group 2, 3, 4, 10, 11, 12 with a centre at 7, and the group 30, 31 with a centre at 30.5.

Five rounds of two operations. That is the whole algorithm, and the quantity it is reducing at every step is inertia: the sum of squared distances from each point to its own centre. For the final answer that is 25 plus 16 plus 9 plus 9 plus 16 plus 25 in the first group, which is 100, plus a quarter and a quarter in the second, for 100.5.

The score cannot tell you how many clusters there are

Anyone reading the eight numbers sees three groups, not two. The obvious next move is to try both and take the better score.

With one cluster, the centre is the mean of all eight, 12.875, and the inertia is 928.9. With two, as computed, 100.5. With three, the groups are 2, 3, 4 at centre 3, then 10, 11, 12 at centre 11, then 30, 31 at centre 30.5, and the inertia is 2 plus 2 plus 0.5, which is 4.5.

Keep going. With eight clusters, every point is its own centre and the inertia is exactly zero.

Inertia falls monotonically as clusters are added, always, by construction, so the score cannot choose the number of clusters. What people do instead is look for the point where the fall stops being dramatic, and on this data it is unambiguous: 928.9 to 100.5 is a collapse, 100.5 to 4.5 is a collapse, and everything after is small change. Three.

Real data rarely bends that clearly, and the scikit-learn demonstration of k-means assumptions starts from exactly this point, noting that in a real setting there is no uniquely defined true number of clusters, and that an appropriate number has to be decided from data-based criteria and knowledge of the intended goal. The second half of that sentence is the operative one. The number of defect types is a question about metallurgy, and the algorithm has no access to metallurgy.

Two shapes where it returns the wrong grouping

The failures that matter are not cases where k-means gets a fuzzy answer. They are cases where it converges confidently to a grouping nobody wanted, and the shape of the data predicts it.

Two arrangements and the boundary k-means settles on. Both answers minimise squared distance to two centres, and both are the wrong grouping.

A ring inside a ring. Points form a small circle and a large circle around the same middle. To a person there are obviously two groups. To k-means, the centre of the inner ring and the centre of the outer ring are the same point, so it cannot place two centres in a way that separates them. It does the only thing that lowers inertia: it cuts the whole picture down the middle, and each cluster ends up with half of the inner ring and half of the outer one. Restarting does not help, because this is not a local minimum. It is the best available answer to the question that was asked.

Two long parallel groups. Points form two elongated diagonal stripes lying side by side. The correct split is between the stripes. The split with the lower inertia is across both of them, because the stripes are long, so the biggest distances in the data run along their length rather than between them. Each returned cluster is one end of both groups.

The scikit-learn clustering documentation names the assumption that produces both results: inertia makes the assumption that clusters are convex and isotropic, which is not always the case, and it responds poorly to elongated clusters, or manifolds with irregular shapes. The same documentation adds the distributional reading, that k-means is equivalent to taking the maximum likelihood estimator for a mixture of gaussian distributions with the same variances but possibly different means. Equal variances, in every direction, for every cluster. If the real groups differ in spread, or are longer in one direction than another, that assumption is doing the deciding.

The demonstration page adds two more scenarios worth knowing by name. Anisotropically distributed blobs, where the groups are stretched, fail because k-means minimises Euclidean distance to a centre and is therefore more appropriate for clusters that are isotropic and normally distributed. Unequal variance fails for the same reason. Unevenly sized groups fail more subtly, and the page is careful here: there is no theoretical result stating that k-means requires similar cluster sizes, but minimising Euclidean distances means that the sparser and more high dimensional the problem is, the more the algorithm needs to be run from different starting centres to reach a global minimum of inertia.

That last point covers the failure people do usually hear about. The documentation states that given enough time k-means will always converge, but possibly to a local minimum, and points at the k-means++ initialisation scheme, which spreads the starting centres out and is the default. It helps with starting positions. It does nothing at all for the two shapes in the drawing.

Two things to fix before running it

Scale the features. k-means is a distance method, so a column measured in rupees and a column measured in counts do not get equal votes; the one with the larger numeric range decides the clustering almost on its own. This is the same preparation question as How a dataset becomes features, except that here getting it wrong does not degrade the answer gracefully. It silently replaces the question.

Reduce the dimensions, or at least know what high dimensions do to distances. The documentation is explicit that inertia is not a normalised metric and that in very high-dimensional spaces Euclidean distances tend to become inflated, an instance of the curse of dimensionality, and it recommends running a dimensionality reduction such as principal component analysis before clustering, which also speeds up the computation. Several hundred measurements per defect image is squarely in that territory.

Deciding whether a clustering means anything

There is no held-out score here. Nobody labelled anything, which is why clustering was reached for, so the discipline of Train, test, and the lie of a single score has no direct equivalent. Three checks stand in for it.

Stability. Cluster a random 80 percent of the rows, twice, with different subsets. If the groups that come back are recognisably the same groups, that is evidence of structure. If the memberships reshuffle, the algorithm was partitioning noise, and it will partition noise reliably and repeatably.

Description. Take each cluster and write one sentence describing it in the original units, before any scaling. Accounts averaging 200 to 400 rupees per order. Defects with high edge contrast and low area. A cluster nobody can describe is not a finding.

Consequence. Ask what somebody would do differently for one cluster than for another. If the answer is nothing, the clustering is a chart. This is the equivalent of the question in What a model actually learns about where the loss and the decision come apart: inertia is a proxy, and the fact that it went down is not evidence that anything useful was found.

When the shapes are wrong for k-means, the fix is a different algorithm rather than a different setting. Density-based methods find groups of any shape, at the cost of two parameters and an explicit category for points that belong to no group. Hierarchical methods produce a tree of nested groupings and let the cut be chosen after looking. Gaussian mixtures relax the equal-variance assumption that the ring and the stripes both violate.

The defect images went to a mixture model on eight principal components, and the plant manager's answer turned out to be four, one of which was images taken under a failing overhead light. That cluster was the most useful output of the project, and it was a fault in the camera rig rather than in the steel.

Reducing several hundred measurements to eight components before clustering is the step that made any of this tractable, and it deserves its own examination, because what those eight components preserve and what they throw away is not what most people assume.

References

  1. Clustering. scikit-learn documentation, version 1.9.0, 2026.
  2. Demonstration of k-means assumptions. scikit-learn documentation, version 1.9.0, 2026.
  3. Decomposing signals in components, Principal component analysis. scikit-learn documentation, version 1.9.0, 2026.

All insights

Working on something like this?

If this is close to something you are trying to solve, tell us where you have got to and we will say what we would test first.

Book a discovery call