scikit-learn
confusion matrix
classification report
machine learning
data analysis

How to interpret scikit's learn confusion matrix and classification report?

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

Introduction

Scikit-learn gives you two very useful views of classifier performance: the confusion matrix and the classification report. The confusion matrix shows where predictions landed, while the classification report turns those counts into precision, recall, and F1 scores for each class.

Read the Confusion Matrix First

In scikit-learn, the confusion matrix is organized as:

  • rows: true labels
  • columns: predicted labels

That orientation is the source of a lot of confusion. If cell (i, j) is large, it means many examples whose true class was i were predicted as j.

Here is a small multiclass example:

python
1from sklearn.metrics import confusion_matrix, classification_report
2
3y_true = [0, 0, 0, 1, 1, 1, 2, 2, 2]
4y_pred = [0, 1, 0, 1, 2, 1, 2, 0, 2]
5
6labels = [0, 1, 2]
7
8cm = confusion_matrix(y_true, y_pred, labels=labels)
9print(cm)
10
11print(
12    classification_report(
13        y_true,
14        y_pred,
15        labels=labels,
16        target_names=["cat", "dog", "fox"],
17        zero_division=0,
18    )
19)

The confusion matrix prints as:

python
[[2 1 0]
 [0 2 1]
 [1 0 2]]

Interpret it row by row:

  • true cat: predicted as cat 2 times, as dog 1 time
  • true dog: predicted as dog 2 times, as fox 1 time
  • true fox: predicted as fox 2 times, as cat 1 time

The diagonal entries are the correct predictions. Everything off the diagonal is a mistake pattern.

What the Classification Report Adds

The classification report summarizes each row and column of that matrix into standard metrics.

For each class:

  • precision: of everything predicted as this class, how much was correct
  • recall: of everything truly in this class, how much was found
  • F1-score: harmonic mean of precision and recall
  • support: how many true samples belonged to that class

Using the cat row from the example:

  • precision for cat uses the cat prediction column
  • recall for cat uses the cat true row

This is why a class can have high recall and mediocre precision, or the reverse. Those metrics answer different questions.

Macro, Weighted, and Accuracy

The bottom rows of the report are often more informative than people realize.

Accuracy

Accuracy is the proportion of all samples classified correctly. It is simple, but it hides class imbalance. A model can look accurate while failing badly on a minority class.

Macro Average

Macro average computes the metric independently for each class, then averages those values equally. Every class gets the same weight, even if one class is rare.

Weighted Average

Weighted average also computes per-class metrics, but weights them by support. Large classes influence the final number more heavily.

If macro average is much worse than weighted average, that is often a sign that small classes are underperforming.

Binary Classification Mapping

For binary problems, people often expect explicit true positive, false positive, false negative, and true negative labels. You can still read those from the matrix, but only after you know which label is treated as the positive class.

For example, with labels [0, 1]:

python
1from sklearn.metrics import confusion_matrix
2
3y_true = [0, 0, 1, 1, 1, 0]
4y_pred = [0, 1, 1, 1, 0, 0]
5
6cm = confusion_matrix(y_true, y_pred, labels=[0, 1])
7print(cm)

The output is:

python
[[2 1]
 [1 2]]

If class 1 is the positive class, then:

  • top-left is true negative
  • top-right is false positive
  • bottom-left is false negative
  • bottom-right is true positive

Common Interpretation Mistakes

Two implementation details matter in practice.

First, class order is controlled by the labels argument or by the sorted unique labels in the data. If you assume the wrong class order, your interpretation will also be wrong.

Second, some classes may have no predicted samples at all. In that case precision can become undefined, which is why zero_division=0 is often useful when generating reports for automation or dashboards.

Common Pitfalls

  • Reading columns as true labels and rows as predictions. In scikit-learn it is the other way around.
  • Using accuracy alone on imbalanced datasets.
  • Forgetting to fix label order when comparing runs.
  • Treating macro and weighted averages as interchangeable. They answer different questions.
  • Ignoring support. A great score on a class with very few examples may not mean much.

Summary

  • The confusion matrix shows true labels by row and predicted labels by column.
  • The diagonal contains correct predictions; off-diagonal cells show error patterns.
  • The classification report turns those counts into precision, recall, F1-score, and support per class.
  • Macro average treats all classes equally, while weighted average favors common classes.
  • Always confirm class order before interpreting any metric.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

ML System Design practice on Codemia

Design recommenders, ranking systems and training pipelines the way ML interviews actually ask for them, with worked solutions.

Practice ML system design

All Rights Reserved.