sklearn Classification Metrics: Confusion Matrix to F1
python sklearn classification metrics confusion matrix precision recall f1: Compute and interpret sklearn classification metrics: confusion matrix, precision, recall,...
python sklearn classification metrics confusion matrix precision recall f1 requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.
Python sklearn classification metrics center on the confusion matrix and the values derived from it: precision, recall, and F1. Accuracy alone hides most of what matters, especially when classes are imbalanced. This article shows how to compute the confusion matrix with sklearn, derive precision, recall, and F1 from it, and use the metric functions that handle the calculations for binary and multi-class models.
Computing the Confusion Matrix with sklearn
The confusion_matrix function takes the true labels and the predicted labels and returns a square matrix. For binary classification the matrix is 2x2; for multi-class problems it is n_classes x n_classes.
from sklearn.metrics import confusion_matrix y_true = [0, 1, 0, 1, 0, 1, 1, 0] y_pred = [0, 0, 1, 1, 0, 1, 0, 0] cm = confusion_matrix(y_true, y_pred) print(cm)
The output is:
[[3 1]
[2 2]]
Rows are the actual classes and columns are the predicted classes. The diagonal holds correctly classified samples: three negatives and two positives. The off-diagonal cells are errors—one negative predicted as positive and two positives predicted as negative.
Reading the Confusion Matrix Layout
For binary classification the four cells have standard names:
| Predicted Negative | Predicted Positive | |
|---|---|---|
| Actual Negative | True Negative (TN) | False Positive (FP) |
| Actual Positive | False Negative (FN) | True Positive (TP) |
- True Negative: negative sample correctly predicted as negative
- False Positive: negative sample predicted as positive (Type I error)
- False Negative: positive sample predicted as negative (Type II error)
- True Positive: positive sample correctly predicted as positive
These names matter because precision and recall are defined directly from these four numbers. Misreading the matrix layout is a common source of errors when interpreting results.
Deriving Precision, Recall, and F1 from the Matrix
Precision answers: of the samples predicted positive, how many were actually positive?
precision = TP / (TP + FP)
Recall answers: of the actual positive samples, how many did the model find?
recall = TP / (TP + FN)
F1 is the harmonic mean of the two, which penalizes a large gap between them:
F1 = 2 * (precision * recall) / (precision + recall)
Using the matrix from the previous example:
tn, fp, fn, tp = cm.ravel() precision = tp / (tp + fp) recall = tp / (tp + fn) f1 = 2 * (precision * recall) / (precision + recall) print(precision, recall, f1)
The ravel() method flattens the matrix in row-major order, so the four values come out as TN, FP, FN, TP—the same order as the layout table. For the example matrix this gives precision 0.667, recall 0.5, and F1 0.571.
Using sklearn's Metric Functions
Deriving the metrics manually is useful for understanding, but sklearn provides dedicated functions that do the same work:
from sklearn.metrics import precision_score, recall_score, f1_score precision = precision_score(y_true, y_pred) recall = recall_score(y_true, y_pred) f1 = f1_score(y_true, y_pred)
For a quick overview of all three at once, classification_report prints precision, recall, F1, and support for each class:
from sklearn.metrics import classification_report print(classification_report(y_true, y_pred))
The report shows per-class metrics plus macro and weighted averages. It is the fastest way to see where a classifier fails and which class is being neglected.
Multi-Class Classification and the average Parameter
For multi-class problems, precision, recall, and F1 are computed per class and then combined. The average parameter controls how:
| average | Behavior |
|---|---|
macro | Mean of per-class metrics, ignoring class size |
micro | Aggregate TP, FP, FN across all classes, then compute |
weighted | Mean weighted by the number of true samples per class |
y_true_multi = [0, 1, 2, 0, 1, 2, 0, 1] y_pred_multi = [0, 1, 1, 0, 2, 2, 0, 1] precision_macro = precision_score(y_true_multi, y_pred_multi, average="macro") precision_weighted = precision_score(y_true_multi, y_pred_multi, average="weighted")
macro treats every class equally, which is appropriate when class sizes differ and performance on the smallest class matters. weighted reflects the actual distribution and is closer to what you would observe on the full dataset. micro computes a single global value and is equivalent to accuracy when applied to all predictions.
When Accuracy Misleads: Imbalanced Data
Consider a dataset where 95% of samples are negative and 5% are positive. A model that predicts negative for everything achieves 95% accuracy but has zero recall for the positive class. The confusion matrix exposes this immediately:
y_true_imb = [0] * 95 + [1] * 5 y_pred_imb = [0] * 100 cm_imb = confusion_matrix(y_true_imb, y_pred_imb) print(cm_imb)
The matrix shows 95 true negatives, 5 false negatives, and no true positives. Precision is undefined because the denominator is zero, recall is 0.0, and F1 is 0.0. Accuracy alone would have suggested a strong model.
This is why precision and recall are reported alongside accuracy for any classification task with an uneven class distribution.
Choosing the Right Metric for Your Problem
The choice between precision and recall depends on the cost of each error type.
When false positives are expensive—for example, a spam filter that blocks legitimate email—precision matters more. When false negatives are expensive—such as fraud detection where missed fraud is the larger loss—recall matters more.
F1 is a single number that balances both, but it assumes precision and recall are equally important. If one error type costs significantly more than the other, optimize the metric that reflects that cost directly rather than relying on F1.
Common Pitfalls with sklearn Metrics
The confusion_matrix function orders classes by sorted label values by default. If your labels are strings or have a non-obvious order, pass the labels parameter explicitly to control the row and column order:
cm = confusion_matrix(y_true, y_pred, labels=["neg", "pos"])
Without this, the matrix layout may not match the TN/FP/FN/TP positions you expect, and any metric you derive manually will be wrong.
The zero_division parameter controls what happens when a denominator is zero. By default sklearn returns 0.0, but you can set it to "warn" to surface the issue:
precision = precision_score(y_true_imb, y_pred_imb, zero_division="warn")
Finally, precision_score, recall_score, and f1_score default to average="binary" and expect exactly two classes. Passing multi-class labels without specifying average raises a ValueError. Set average explicitly whenever your problem is not binary.