← Part of Lysen · lysen.org
Lysen ML
← All algorithms Unsupervised · clustering

K-means

The problem it solves: you have data, and nothing is labelled. Nobody has told you which rows belong together, or even how many kinds of row exist. Clustering is the family that hunts for that hidden structure on its own, and K-means is its workhorse, simple enough to run by hand and fast enough for millions of rows.

The idea in one sentence: guess where the group centers are, then let the data correct your guess. Every point joins whichever center is nearest, then every center slides to the middle of the points that joined it, and you repeat until nothing moves. All the depth is in what surrounds it: how you start it, how you check it, and knowing when it is fooling you.

Used for customer segmentationimage colour compressiongrouping documentsflagging unusual recordsexploring data before modelling
Learning typeUnsupervised
Primary taskClustering
MechanismDistance based

Running example for the whole chapter: the customers of a café. Each point is one customer, where x = visits per month and y = average spend in euros. The owner suspects there are different types of customer but has never labelled anybody. Can the data tell us?

01

Intuition: what it does, and how

What it does. Imagine you own a café and you have a dot on a chart for every customer. Nobody has told you what kind of customer each one is. K-means takes that cloud of dots and splits it into k groups, where you pick the number k yourself. Each group gets one point that represents it, called a center. You can think of it as the imaginary average customer of that group.

How it does it. The whole method is two moves, repeated. Assign: every dot joins whichever center is nearest right now. Update: every center slides to the average position of the dots that just joined it. Each move makes the other slightly out of date, so you simply do them again, a bit like a shaken box of marbles settling down.

1a The problem, before any algorithm

This is exactly what the café owner has. Dots, no names, no colours. Look at it for a moment and your eye has probably already found the groups by itself. Clustering is the attempt to give a computer that same instinct, using nothing but the distances between points.

One honest warning before we start. Your eye is also the reason clustering is risky, because people see groups in completely random data too. Module 3 is about telling the difference.

1b Be the algorithm: run the two moves by hand

cluster 1 cluster 2 cluster 3 unassigned
Click the plot to drop 3 centers (0/3 placed), or press Place 3 at random. Bad placements are welcome here, because watching them recover is the point.

Two experiments. First, drop all three centers in one corner and press the buttons. Watch the loop untangle itself; that self-correction is the whole intuition. Second, drop two centers inside the same visible group and see whether they ever escape. Sometimes they do not. Remember that, because it comes back as failure mode 4a.

02

The algorithm: every step of the loop

What you just did by hand is written out below as a recipe. Programmers call it pseudocode: the steps in order, in words, with nothing in it that belongs to any one language.

1initialize k centers μ₁ … μₖ // place the starting centers
2repeat:
3 assign: cᵢ ← argminⱼ ‖xᵢ − μⱼ‖ // each point joins its nearest center
4 update: μⱼ ← mean of points with cᵢ = j // each center moves to its average
5until assignments stop changing // nothing moved, so stop

Those symbols look worse than they are. μ (say "mew") is the name for a center, μⱼ is center number j, xᵢ is data point number i, the double bars ‖ ‖ mean "the distance between", and argmin means "whichever one gives the smallest answer". So line 3 reads: each point looks at the distance to every center and joins the closest one.

2a The score it is quietly shrinking

J = Σⱼ Σx∈Cⱼ ‖x − μⱼ‖² // the score the algorithm shrinks
…J at this step …points that changed group

Read J out loud as: for every group, take each point, measure how far it is from its own center, square it, and add everything up. One number for the whole clustering, and smaller is better; people call it WCSS. Assigning sends every point to its nearest center, so it cannot make J worse. Moving each center to the average is the best possible spot, so that cannot either. A number that never rises and cannot fall forever has to stop falling, which is why the loop always halts. Notice the word that is missing from that promise: best.

CuriousWhy the mean, and why is that the same question as the squaring?

Line 4 says each center moves to the mean of its points. That looks like an obvious choice and it is not one: it is forced by the squares in J, and the two travel together.

Hold the assignments still and ask where one center should sit. You want the μ that makes Σ‖x − μ‖² as small as possible, so differentiate that sum with respect to μ and set it to zero:

d/dμ Σ (x − μ)² = −2 Σ (x − μ) = 0
// so Σx − nμ = 0, so μ = (Σx) / n

The mean is not a sensible summary somebody chose. It is the exact solution, and it is the answer only because the score squares. Swap the squares for plain distances and the same argument lands on the median instead, which is an algorithm with its own name, k-medians.

That is worth holding onto, because it explains the failure you can drag around in before you get there. Squaring makes a far-away customer shout, the mean has to listen, and the center goes to meet them. A median would barely move. The outlier problem is not a bug in the update step; it is the price of the score, and the same trade shows up in linear regression for exactly the same reason.

CuriousIf J always falls, how can the silhouette have a peak?

Jumping ahead to module 3 for a moment, because the two scores there behave so differently that it looks like one of them must be broken. J falls every time you raise k. The silhouette does not. Both are measured on the same clustering.

J only ever asks one question: how far is each point from its own center? Give the algorithm another center and every point can only end up nearer to one, or stay where it is. So J falls, always, all the way down to zero when there are as many centers as customers. It is not measuring whether the groups are any good. It is measuring how tightly they are packed, and more groups are always tighter.

The silhouette asks a second question alongside the first: how far is each point from the group next door? That is what changes everything. Split a real group in half and you have made both halves tighter, which J likes, but you have also put every point in one half right next to a different group, which the silhouette hates. The two effects pull against each other, so the score has somewhere to peak.

The general lesson is worth more than the two formulas. A score with one term usually has a trivial optimum you can reach by pushing that term to its limit, and a score that actually chooses between models almost always has two terms in tension. You will meet that shape again as the bias and variance trade, where it is the whole page.

03

Evaluation: scoring a model when nobody knows the answer

Most models can be marked like a test, because someone wrote down the correct answers. Clustering has no answer key, so instead we score the shape of the result, using numbers worked out purely from the geometry. Together they answer the question the algorithm never asks you: what should k be?

Every point here is a complete run of K-means, best of eight attempts. J always falls as k grows. With as many centers as customers it would hit zero and tell you nothing. So you do not look for the lowest point, you look for the bend. Click any k to inspect it.

3chosen k …J (WCSS) …silhouette
s(x) = ( b(x) − a(x) ) / max(a(x), b(x))
// a = mean distance to my own group
// b = mean distance to the nearest other group

The silhouette asks each point: am I closer to my own group, or to the group next door? It lands between +1 and −1, and unlike J it does not always improve as k grows, so it has a genuine peak. Here both methods point at k = 3. When they disagree on real data, that is useful information: it usually means your groups are not neat round blobs.

04

Failure modes: break it, then fix it

Two things go wrong often enough to have names. Each one is a lever you can pull on the interactive below, and each has a defence you can write into a prompt in module 5.

4a One extreme customer moves the whole center

Drag the ringed customer anywhere on the plot. Its center follows, because a mean has no defence against an extreme value.
0.0center moved by 0points that changed group

Why it happens. The update step takes an ordinary average, and an average is dragged by whatever is furthest out. One customer who spent €400 can bend a whole segment around themselves. What to do: inspect extreme values before clustering rather than after, and if they are real and you cannot drop them, use K-medoids, whose centers must be actual customers and therefore cannot drift into empty space.

4b An unlucky start it never escapes

…

Same data, same k, same code. The only difference is where the centers happened to start. K-means is guaranteed to stop, but not guaranteed to stop anywhere good, so a single run is never evidence. What to do: start with k-means++, which spreads the first centers out on purpose, and run it ten times keeping the lowest J. Both are one argument each in every library, and both are missing from the lazy prompt in module 5.

05

Prompting AI: making an assistant build it properly

An assistant will happily write K-means from the laziest possible request. The difference between a weak prompt and a strong one is not the quality of the code, it is whether the traps from modules 3 and 4 get handled or quietly skipped.

"Cluster my customer data with k-means in Python."

What you typically get back

Working code that picks k = 3 for no stated reason, uses the raw columns without rescaling, starts once, and finishes with a confident summary. It runs. It also decides how many customer groups your business has on your behalf, ignores that euros and visit counts live on different scales, and gives you no way to check whether the groups are real.

k chosen for youno feature scalingno elbow or silhouetteone start, no repeatsno outlier checkno interpretation
06

Beyond AI: choosing the tool, owning the call

Two things survive even a perfect prompt. The first is the choice of algorithm. An assistant reaches for K-means because everybody does, but whether that is right depends on features of your data you have to notice yourself. The second is the set of judgment calls, the questions with no score attached at all.

If your problem looks like thisReach forBecauseThe price you pay
Compact, roundish groups of similar size, numeric columns, a large dataset, and speed matters K-meansthis chapter Fast and simple, handles millions of rows, and centers describe as an average member. You must pick k. Sensitive to outliers, starting positions and scale. Assumes round groups.
Outliers you cannot remove, or you want each center to be a real example K-medoidsalso called PAM Centers are actual data points, so extreme values cannot drag them, and any distance measure works. Much slower; painful beyond roughly 10,000–50,000 rows. You still pick k.
You do not know how many groups exist, shapes are irregular, and some points belong to nothing DBSCANnot covered here A group is a crowded region, so it finds any shape, labels leftovers as noise, and never asks for k. Two fiddly settings, and it struggles when some groups are much denser than others.
Groups that overlap, or you want "70% group A, 30% group B" instead of one hard label Gaussian mixtureGMM Percentage membership rather than a single label, and stretched oval groups at any angle. More settings to fit, still sensitive to starting positions, still assumes blob shapes.

6b The judgment calls no prompt makes for you

Judgment call

Do the groups mean anything?

K-means will split pure noise into k groups, draw a convincing chart and post a decent silhouette. Whether "group 2" is a real type of customer worth a marketing budget is a business question. No score answers it.

Judgment call

Which columns, and on what scale?

Cluster on visits and spend and you get loyalty groups. Add age and postcode and you get different people entirely. Choosing what "similar" means is the biggest decision, and it happens before any code runs.

Data reality

Outliers: mistakes or discoveries?

Module 4a treated an outlier as a threat to the average. But the customer spending €400 might be the most valuable thing in your data. Typing error or real signal is a question about where the data came from.

Responsibility

Acting on the groups is on you

Charging "group 3" more, or leaving them out of an offer, can quietly repeat a bias hidden in the columns you chose. The algorithm optimised a number. The consequences were never in the formula.