Concepts / The F-Score and Precision-Recall Trade-off

The F-Score and Precision-Recall Trade-off

The source makes the point that precision and recall are separate questions, using rows from the digit classifier's report.

  • Programming

Why One Accuracy Number Can Mislead

A common first instinct, when a classifier scores well, is to treat the accuracy number as a verdict. If a model is correct on most of its test examples, it seems reasonable to conclude that it works. In a binary problem that conclusion is at least easy to check, because there are only two outcomes to keep track of. Multiclass problems are different. When there are ten or more possible labels, a single fraction hides which labels the model handles well and which ones it struggles with.

Multiclass accuracy is defined the same way as before: it is the fraction of correctly classified examples. The problem appears when the classes are imbalanced. Imagine a three-class problem in which 85% of the points belong to class A, 10% belong to class B, and 5% belong to class C. Consider a model that has learned nothing useful and simply predicts class A for every point. Work through the consequences before reading on.

What do you think happens?

The model predicts class A for all 100 points. What is its accuracy, and what is its recall for class B?

  • Accuracy 85%, recall for B is 0%

  • Accuracy 50%, recall for B is 50%

  • Accuracy 10%, recall for B is 100%

Reveal answer
Answer:

Accuracy is 85% and recall for class B is 0%.

Exactly 85 of the 100 points are class A, so always predicting A is correct 85 times, giving 85% accuracy. Class B has 10 true members and none are found, so recall for B is 0. The same happens for class C. A headline accuracy of 85% therefore says nothing about whether the model finds the minority classes at all.

The lesson is not that accuracy is always worthless. It is that an accuracy value must be read alongside information about how the errors are distributed across classes. The tools in the rest of this article supply that information: the confusion matrix, the per-class precision, recall, and f-score, and the ways those per-class values are averaged into one number.

Reading the Confusion Matrix Grid

A confusion matrix places true labels in rows and predicted labels in columns. Each cell counts how many examples with a given true label received a given predicted label. The diagonal, where row and column match, holds the correct predictions. Every off-diagonal cell is a confusion: a true class being predicted as some other class. Reading the grid row by row tells you where each true class's examples went.

The grid below is a small generated example with 100 points, matching the 85, 10, and 5 class sizes from the imbalance example. Row A holds 85 true A points, row B holds 10, and row C holds 5. Read the nonzero off-diagonal cells: they are the confusions.

true A, pred A83true A, pred B2true A, pred C0true B, pred A3true B, pred B5true B, pred C2true C, pred A1true C, pred B1true C, pred C3
Which true class is being predicted as which other class, and where do those errors appear in the grid? Off-diagonal changed cells are confusions; the diagonal holds correct predictions.

Read the grid this way. Row B has 10 true members, of which 5 are correct, 3 were predicted as A, and 2 were predicted as C. Column A, by contrast, collects 87 predictions, most of them correct, but also picks up one true C point and three true B points. The grid shows which class pairs are confused, and in which direction, something no single accuracy number reports.

The source applies this reading to a real task: classifying the ten handwritten digits in the digits dataset. A logistic regression model is trained on part of the data, predicts labels for the held-out test set, and then has its accuracy and confusion matrix printed. The reported accuracy is 95.3%, which the source describes as a sign that the model is doing pretty well. The matrix is where the more detailed story begins, and the source also shows the same counts as a colored heatmap with predicted labels on the horizontal axis, true labels on the vertical axis, and digit names as ticks. The heatmap is only a visual version of the grid, so learning to read the raw numbers first is worthwhile.

Per-Class Precision and Recall

A confusion matrix is detailed but dense. Per-class precision and recall condense it into two numbers for each class, computed by treating that class as the positive class and every other class as negative. Precision asks whether a prediction of a given class can be trusted. Recall asks whether every true member of that class was found.

Rule

Here TP is the count of true positives for class c, FP is the count of examples predicted as c that belong to another class, and FN is the count of examples of class c that were predicted as something else. In the grid, the diagonal cell for class c supplies TP, the rest of its column supplies FP, and the rest of its row supplies FN.

All 100 samplesPositive: true B (10)class B treated as positiveNegative: true A andC (90)all other classes togetherTP: 5true B predicted BFN: 5true B predicted A or CFP: 3true A or C predicted BTN: 87negatives not predicted Bsplit by true classsplit by true classpredicted Bpredicted otherwisepredicted Bpredicted otherwise
For class B, how are the 100 samples split into positive and negative groups so that precision, recall, and the binary f-score can be computed for it?
Worked example

Precision and recall for class B

Using the generated 100-point grid, compute precision and recall for class B treated as the positive class.

  1. 1
    Find TP

    The diagonal cell for B holds 5 true B points predicted as B, so TP is 5.

  2. 2
    Find FP

    Column B totals 8 predictions. Subtracting the 5 correct ones leaves 3 false positives: 2 from true A and 1 from true C.

  3. 3
    Find FN

    Row B totals 10 true members. Subtracting the 5 correct ones leaves 5 false negatives: 3 predicted A and 2 predicted C.

  4. 4
    Compute precision

    Precision is $\frac{5}{5+3} = 0.625$. Of the 8 predictions labeled B, 5 can be trusted.

  5. 5
    Compute recall

    Recall is $\frac{5}{5+5} = 0.5$. Of the 10 real B points, only half were found.

Result

Class B has precision 0.625 and recall 0.5. Its precision is higher than its recall, so the model is more reliable when it says B than it is at finding every B.

The source makes the point that precision and recall are separate questions, using rows from the digit classifier's report. Class 0 has precision and recall both equal to 1, because no confusions involve that class. Class 7 has precision 1, meaning no other digit was mistakenly predicted as 7, yet its recall is lower at 0.94, meaning a few true 7s were missed. Class 6 has recall 1, because no digit 6 was missed, even though its precision is not perfect. A model can therefore be trustworthy in one direction and incomplete in the other.

Reading a Classification Report

A classification report condenses the confusion matrix into one row per class, with precision, recall, and f-score for each, and usually a support count showing how many true examples that class has. The source computes it with the classification_report function. The code below sets up the digits task so the report can be produced. The imports use the standard scikit-learn locations for each function involved.

python
Notes on the code
  • load_digits supplies the ten handwritten digit classes
  • y_pred holds the predicted label for every held-out test example
  • classification_report prints one row per digit with precision, recall, f1-score, and support

Read the report one row at a time. Each row answers three questions for one class: how often a prediction of that class was right (precision), how often that class was found (recall), and the single balanced score combining them (f-score). The support column tells you how many true examples of that class were in the test set, which is the context needed to judge how much each row should matter.

The per-class rows are also where the model's trouble spots appear. In the digit report, class 8 has the lowest f-score at 0.91, which makes it the first row to inspect when the overall score needs explaining. The source also flags class 3 as a problem row, because its precision is lower than most of the others. These are the rows to examine before trusting the headline 95.3% accuracy.

Macro, Weighted, and Micro Averages

For imbalanced multiclass data, the source describes the most commonly used metric as the multiclass version of the f-score. The method is to compute one binary f-score per class, treating that class as positive and all other classes together as negative. That produces one f-score for each class, and a final single number is obtained by combining those per-class values in one of three ways.

The source computes the micro and macro averages on the same test predictions using the f1_score function with its average argument set to each strategy. The source's version of that line was incomplete, so the corrected form is shown below.

python
Notes on the code
  • average='micro' pools the counts of all classes before computing one f-score
  • average='macro' takes the unweighted mean of the per-class f-scores
  • average='weighted' takes the mean of per-class f-scores weighted by each class's support
Per-class F1 scoresA 0.965, B 0.556, C 0.600Per-class TP, FP,FNsummed across classesMacro: 0.707unweighted mean, each classequalWeighted: 0.906weighted by support, 85,10, 5Micro: 0.91pooled counts, each sampleequalequal weightsupport weightpooled
How per-class f-scores or counts are combined into one number, and how macro (equal class weight), weighted (support-based weight), and micro (pooled counts) differ.
Worked example

Computing all three averages on the generated grid

Using the 100-point grid from earlier, with class sizes 85 for A, 10 for B, and 5 for C, compute the macro, weighted, and micro averages of the f-score.

  1. 1
    Per-class f-scores

    Class A has precision 83/87 and recall 83/85, giving F1 of about 0.965. Class B has F1 of about 0.556. Class C has precision 0.6 and recall 0.6, giving F1 of 0.6.

  2. 2
    Macro average

    Take the unweighted mean: $\frac{0.965 + 0.556 + 0.600}{3} \approx 0.707$. Class C counts as much as class A.

  3. 3
    Weighted average

    Weight each F1 by its support: $\frac{85(0.965) + 10(0.556) + 5(0.600)}{100} \approx 0.906$. The large class dominates.

  4. 4
    Micro average

    Pool the counts: TP is 83 + 5 + 3 = 91, FP is 4 + 3 + 2 = 9, FN is 2 + 5 + 2 = 9. Then precision and recall both equal $\frac{91}{100} = 0.91$, so micro F1 is 0.91.

  5. 5
    Compare

    The macro value is pulled down by the weak minority class B, while the micro value treats every sample equally and so stays close to the overall accuracy.

Result

Macro 0.707, weighted 0.906, micro 0.91. The same confusion matrix yields three different headline numbers, and the difference comes entirely from how classes or samples are weighted.

Averaging methodHow it combines classesWhat it emphasizesResult on the generated grid
MacroUnweighted mean of per-class f-scoresEach class matters equally0.707
WeightedMean of per-class f-scores weighted by supportLarger classes count more0.906
MicroPooled TP, FP, and FN across all classesEach sample matters equally0.91

Three ways to average the f-score across classes

Choosing an Average for Your Problem

The source gives a direct rule for choosing between the two most common options. If each sample matters equally, the source recommends the micro average f1-score. If each class matters equally, it recommends the macro average f1-score. The choice is about what the application is trying to protect, not about which number happens to be higher.

Apply the rule to the generated grid. If the business cares most about the common case and every individual prediction counts equally, micro's 0.91 is the relevant figure. If the rare classes matter as much as the common one, for example because missing class C is costly regardless of its size, macro's 0.707 reveals the weakness that micro hides.

  • Common mistake

    Treating a high accuracy as proof that every class is handled well

    What it looks like

    A model that always predicts the majority class on the 85/10/5 dataset still reports 85% accuracy.

    Why it fails

    Accuracy pools all samples together, so a large class can hide complete failure on small classes.

    Do this instead

    Check the confusion matrix and the per-class report before trusting the headline number.

  • Common mistake

    Reading precision and recall as the same thing

    What it looks like

    Class 7 in the digit report has precision 1 but recall 0.94.

    Why it fails

    Precision concerns the trustworthiness of predictions of a class, while recall concerns whether all true members were found.

    Do this instead

    Read the two columns separately and identify which kind of error each row shows.

  • Common mistake

    Choosing the average that gives the larger number

    What it looks like

    Micro gave 0.91 and macro gave 0.707 on the same predictions, so picking micro because it looks better.

    Why it fails

    The source ties the choice to what each sample or class is worth in the application, not to the score.

    Do this instead

    Decide first whether each sample or each class matters more, then pick micro or macro accordingly.

  • Common mistake

    Reading the grid's rows and columns backward, so that a true class is mistaken for a predicted class

Practice: Recall for Class C

EASY

Using the generated 100-point grid (row C: 1 predicted A, 1 predicted B, 3 predicted C; column C: 2 predictions from true B and A combined with C's own 3 correct), find the recall for class C and name the true classes whose C samples were missed.

Hints
  • Recall for a class is TP divided by the row total of that class, since FN plus TP equals the true count.
  • Class C has 5 true members, and 3 of them are on the diagonal.
  • The off-diagonal cells in row C show where the missed C samples went.

Key Takeaways

  • Accuracy is the fraction of correctly classified examples, but on imbalanced multiclass data it can hide classes that are almost never found, so the confusion matrix and per-class report must be checked alongside it.
  • In the confusion matrix, true labels are rows and predicted labels are columns, and off-diagonal cells are the confusions between classes.
  • Per-class precision asks whether predictions of a class can be trusted, and recall asks whether every true member of that class was found; the classification report gives both with an f-score and support for each class.
  • Macro averages weight each class equally, weighted averages weight by support, and micro averages pool all counts so each sample matters equally; the source recommends micro when each sample matters equally and macro when each class matters equally.

Related concepts

More concepts starting with T