Clustering Evaluation without Ground Truth
A cluster label is an arbitrary name. Two labelings that give the same points the same grouping are the same clustering, even when every individual number differs.
Why Counting Matching Labels Feels Right
A very common first instinct when checking a clustering result is to compare its labels with a known answer and count how many labels match. That instinct comes from classification, where a predicted class either equals the true class or it does not. Applied to clustering, the same instinct produces a wrong verdict. This article follows that mistake step by step, shows exactly where the evaluation goes wrong, and replaces it with a metric that measures what a clustering actually is.
The lesson is best learned by tracing a small comparison script. Before each result is printed, you will be asked to predict it. The first printed result that disagrees with your prediction marks the place to examine most closely.
What a Cluster Label Really Is
When a clustering algorithm returns an array of numbers, each number is a cluster label. If a reference array of true labels exists, it seems natural to ask whether the two arrays agree, element by element. accuracy_score does exactly that: it checks each position and reports the fraction of positions where the two values are identical.
The trouble is that the numbers in a clustering are arbitrary names. A cluster labeled 0 in one run might be labeled 1 in another run, with no change to which points are grouped together. The meaningful content of a clustering is which points share a group, not which integer each group received.
A cluster label is an arbitrary name. Two labelings that give the same points the same grouping are the same clustering, even when every individual number differs.
Two Labelings of the Same Five Points
Consider five points. The first labeling puts points 0 and 1 in group 0, points 2 and 3 in group 1, and point 4 in group 2. The second labeling puts the same points together, but uses different names: points 0 and 1 get 1, points 2 and 3 get 2, and point 4 gets 0. Nothing about the grouping has changed. Only the names have been rotated.
0.0
1.0- labels_a and labels_b describe the same grouping with different numeric names
accuracy_scorecompares the two lists position by positionadjusted_rand_scorejudges which points share a group
Read the diagram position by position. Every position disagrees, so accuracy_score reports 0.0 even though the grouping is identical. The metric is not measuring whether the points are grouped correctly; it is measuring whether the same integer sits at the same position in both lists.
Predicting the Printed Scores
What do you think happens?
Both labelings describe the same grouping. What does accuracy_score print for labels_a and labels_b?
Reveal answer
0.0
Every position holds a different integer in the two lists (0 vs 1, 0 vs 1, 1 vs 2, 1 vs 2, 2 vs 0), so no position matches and the fraction of matching positions is 0.0.
What do you think happens?
What does adjusted_rand_score print for the same two labelings?
Reveal answer
1.0
adjusted_rand_score judges whether points share a group, and these two labelings group the points identically, so it reports perfect agreement.
Tracing the Comparison Script Step by Step
To locate the divergence, follow the script in order and compare each printed output with your prediction. The first line whose output disagrees with what you expected is the place to examine. The flowchart below lists the steps in execution order.
Finding the first line that disagrees with the prediction
You predicted that both metrics would report perfect agreement, because the two labelings describe the same grouping. Which printed line diverges from that prediction?
- 1Check the first printed line
accuracy_scoreprints 0.0. The prediction was 1.0, so this line already disagrees. - 2Locate the divergence
The disagreement comes from the
accuracy_scorecall, not from the data or the grouping. The labelings are correct; the assumption behind the call is what fails. - 3Check the second printed line
adjusted_rand_scoreprints 1.0, which matches the prediction. The grouping-based metric agrees with the expectation.
The first divergence is the accuracy_score line. It rests on the assumption that identical integers must appear at identical positions, which is not a property of clusterings.
Why Position Matching Fails for Clusterings
accuracy_score requires the exact names to match. For classification this is a reasonable demand, because the predicted class is meant to be the true class. For clustering, the integers are arbitrary, so requiring them to match asks the wrong question. A metric that rewards identical integers will penalize a grouping that is correct but named differently.
Each matched pair of groups holds exactly the same points, even though the numbers attached to them differ. A metric that asks only which points share a group sees identical clusterings here. accuracy_score asks which integer sits at each position, and sees none in agreement.
Choosing a Metric That Judges Grouping
The source names two suitable alternatives: adjusted_rand_score and normalized_mutual_info_score. Both are designed to compare a clustering with a reference grouping while ignoring the label names. When choosing between them, keep one question in mind: does the metric depend on which integer each point receives, or only on which points share a group? A metric that depends only on shared groups fits clustering evaluation.
adjusted_rand_score checks whether points share a group across the two labelings. Renaming the groups leaves that structure unchanged, so the score is not penalized for names.
from sklearn.metrics import accuracy_score
labels_a = [0, 0, 1, 1, 2]
labels_b = [1, 1, 2, 2, 0]
print(accuracy_score(labels_a, labels_b))accuracy_score reports 0.0 because no position holds the same integer in both lists
from sklearn.metrics import adjusted_rand_score
labels_a = [0, 0, 1, 1, 2]
labels_b = [1, 1, 2, 2, 0]
print(adjusted_rand_score(labels_a, labels_b))adjusted_rand_score reports 1.0 because the grouping of the points is identical
Mistakes That Hide the Grouping Question
Common mistake Treating a low accuracy_score as proof that the clustering is poor
What it looks likeaccuracy_score(labels_a, labels_b) returns 0.0 even though both lists group the five points identically.
Why it failsaccuracy_scorerewards identical integers at identical positions. Renamed but identical groups score zero.Do this insteadUse a metric that depends only on which points share a group, such as adjusted_rand_score.
Common mistake Assuming label 0 in one run means the same group as label 0 in another run
Why it failsA cluster label is an arbitrary name. The same integer can refer to different groups in different runs.
Do this insteadCompare the points grouped together, not the integers attached to them.
Common mistake Stopping the trace at the final printed number instead of the first line that disagrees with the prediction
When No Reference Grouping Exists
Everything above assumes a reference grouping exists to compare against. Often it does not. The source treats evaluating clustering without ground truth as a distinct challenge, separate from comparing against known labels.
The lesson that carries over is this: whatever method you choose must judge the grouping, and it must not depend on arbitrary label names. This article does not cover the specific methods used when no reference exists.
Practice: Relabel and Predict
Take labels_a = [0, 0, 1, 1, 2] and create a new labeling labels_c that groups the points in the same way but uses the names 2, 2, 0, 0, 1. Before running any code, predict the printed value of accuracy_score(labels_a, labels_c) and adjusted_rand_score(labels_a, labels_c). Then check your predictions and identify the first line whose output disagrees with them, if any.
Hints
- Write the position-by-position pairs first: (0,2), (0,2), (1,0), (1,0), (2,1).
- Ask whether any pair in that list matches exactly.
- For
adjusted_rand_score, ask whether the points in labels_a and labels_c share groups in the same way.
Key Takeaways
- A cluster label is an arbitrary name; the meaningful content of a clustering is which points share a group.
accuracy_scorecompares labels position by position and requires the exact names to match, so it reports misleading results for a correct grouping with different names.adjusted_rand_scoreandnormalized_mutual_info_scorejudge the grouping rather than the label names, so they suit clustering evaluation.- To find a divergence, compare each script step with your prediction and locate the first line whose output disagrees.
- Evaluating clustering without ground truth is a separate challenge, because metrics that compare against a reference need one to exist.