Move the threshold and watch the confusion matrix rearrange itself. One model, and every score in the table changes.
Overview
One model, many scores
A classifier doesn't output a class. It outputs a score — how plus it thinks each case is. And a class only appears once you compare that score against a threshold.
The histogram shows both spreads: actual negatives in grey, actual positives in orange, shared in the middle because the model is good and not perfect. The dashed line is the threshold.
Move it. each number below the chart changes, and the model hasn't been retrained. The scores are properties of the threshold as much as of the model, which is the single most handy thing to understand here.
Precision, Recall and F1
This module needs JavaScript: the
numbers are computed in the page rather than recorded.
Worth knowing
Precision: of the things you flagged, how many were right. It punishes false positives.
Recall: of the things that were there, how many you found. It punishes false negatives.
They trade off. Lower the threshold and recall rises while precision falls; raise it and the reverse.
F1 is their harmonic mean, which stays low unless both are high. An arithmetic mean would not.
Precision, Recall and F1
Four counts in a table, three ratios drawn from them. One slider that moves all of it.
The four counts
Predicted positive
Predicted negative
Actually positive
True positive
False negative
Actually negative
False positive
True negative
All else is a ratio of these. The two that matter most divide by different denominators, which is just why they disagree.
Precision = TP / (TP + FP). Of all you flagged, what fraction was right. The denominator is what *you* predicted. So Precision is damaged by false alarms.
Recall = TP / (TP + FN). Of all that was really there, what fraction you caught. The denominator is what *reality* held, so recall is damaged by misses.
Why they trade off
Drag the threshold to 0.10. Almost all is flagged, so almost each real plus is caught and recall approaches 100%. But the flagged set is now full of negatives, and precision merges.
Drag it to 0.90. Only the most confident cases are flagged, nearly all of them correct, and precision approaches 100%. But most real positives are below the line, and recall merges.
You can't raise both by moving the threshold. The threshold only chooses where on the trade-off you sit. Raising both at once needs a better model — one whose two spreads share less.
Which one you want depends on the cost
The question is never "which metric is best". It's which mistake is more costly.
Recall matters more when a miss is costly: screening for a serious disease, detecting fraud, finding safety defects. A false alarm costs a second look. A miss costs the thing you were trying to prevent.
Precision matters more when a false alarm is costly: flagging accounts for suspension, recommending content, sending an alert that wakes someone. Missing one is a shame. Being wrong again and again destroys trust in the system.
That is the harmonic mean, and the choice of mean is the point. Take precision of 1.0 and recall of 0.01. A model that flags just one case and gets it right. The arithmetic mean is 0.505. This Sounds fair. F1 is 0.0198.
The harmonic mean is pulled toward the smaller number. So It stays low unless both are high. That makes it hard to game with a collapse model, which is just what a single summary number needs to be.
F1 weights the two equally. This Is a choice and often the wrong one. F-beta lets you weight recall β times as much as precision. F2 favours recall, F0.5 favours precision. If you've a reason to prefer one, use it.
Why accuracy is on the readout and not in the headline
Fit is (TP + TN) / all. It's the most natural metric and it's close to useless when the classes are unbalanced.
If 1% of transactions are fraudulent, predicting "never fraud" scores 99% fit while catching nothing at all. Precision and recall are both zero, which is the honest description. Imbalanced data is where this matters most.
The same model at two thresholds
Precision and recall are properties of the threshold as much as the model, which a worked confusion mat makes concrete. The same classifier, the same scores, two cuts:
threshold
caught (of 100 real)
false alarms
precision
recall
0.10 (permissive)
98
300
0.246
0.98
0.90 (strict)
40
4
0.909
0.40
Drop the threshold and recall climbs toward 100% as almost all is flagged, but the flagged set fills with negatives and precision merges. Raise it and precision climbs as only confident cases live. But Most real positives fall below the line and recall merges. The threshold only chooses *where on the trade-off you sit* — raising both at once needs a better model, one whose plus and minus score spreads share less. F1 summarises a single point as the harmonic mean, 2PR/(P+R), and the choice of *harmonic* is the point: precision 1.0 with recall 0.01 means to a fair-looking 0.505 arithmetically but an F1 of just 0.0198. The harmonic mean is dragged to the smaller number and refuses to reward a model that flags one case and hides.
Which error to cut is a question about costs, never about which metric is "best". Recall matters more when a miss is costly. Screening for a serious disease, catching fraud — where a false alarm costs only a second look. Precision matters more when a false alarm is costly — suspending an account, paging a human at 3am. Where a miss is merely dealt with later. And fit, the most natural metric, is close to useless under imbalance: if 1% of transactions are fraud, predicting "never fraud" scores 99% while catching nothing, with precision and recall both zero telling the honest story the single fit number hides.
Where it goes wrong with Precision, Recall and F1
Reporting one number without the threshold. "Precision 0.9" is uninterpretable alone. At some threshold nearly each model reaches it.
Optimising F1 when the costs aren't equal. F1 assumes they're.
Checking models at 0.5. Two models can rank cases equally well and differ only in calibration. Compare across thresholds, or tune each one.
Fit on imbalanced data. It measures the class balance more than the model.
Questions people ask about Precision, Recall and F1
What is the difference between precision and recall? Precision is the share of positive predictions that are right. Recall is the share of actual positives you caught.
When should I favour precision over recall? When false alarms are costly, such as flagging legitimate transactions as fraud. Favour recall when missing a case is worse, like cancer screening.
Why does F1 use a harmonic mean? It is pulled towards the lower of the two values, so a model cannot hide terrible recall behind high precision.
Why not just use accuracy? On imbalanced data a model that always predicts the majority class scores high accuracy while catching nothing.
What are macro, micro and weighted averages? Macro averages the per-class scores equally, micro pools all the counts, and weighted averages by class size. Macro treats rare classes as equally important.
Can I raise both precision and recall? At a fixed model, changing the threshold trades one for the other. To improve both, you need a better model or better features.
The trade you cannot avoid
Precision and recall pull in opposite directions. Sweeping the choice threshold shows just how much of one each unit of the other costs.
example_01.pyscikit-learn
import numpy as np
from sklearn.datasets import make_classification
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.metrics import precision_score, recall_score, f1_score
X, y = make_classification(n_samples=6000, n_features=15, n_informative=5,
weights=[0.9, 0.1], flip_y=0.08, random_state=0)
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.35, random_state=0,
stratify=y)
prob = LogisticRegression(max_iter=2000).fit(Xtr, ytr).predict_proba(Xte)[:, 1]
print("%10s %11s %9s %9s %9s %9s"
% ("threshold", "flagged", "precision", "recall", "F1", "missed"))
for t in (0.05, 0.10, 0.20, 0.35, 0.50, 0.70, 0.90):
pred = (prob >= t).astype(int)
print("%10.2f %11d %9.4f %9.4f %9.4f %9d"
% (t, pred.sum(),
precision_score(yte, pred, zero_division=0),
recall_score(yte, pred, zero_division=0),
f1_score(yte, pred, zero_division=0),
((pred == 0) & (yte == 1)).sum()))
print()
print("there are %d real positives in this test set." % (yte == 1).sum())
print()
print("precision: of everything you flagged, how much was right.")
print("recall: of everything that was right, how much you flagged.")
print("lowering the threshold flags more, so recall rises and precision falls.")
print()
print("F1 is their harmonic mean, which is harsh on imbalance between them:")
for p, r in ((0.9, 0.9), (0.95, 0.85), (1.0, 0.5), (0.5, 1.0)):
print(" precision %.2f, recall %.2f -> arithmetic %.3f, F1 %.3f"
% (p, r, (p + r) / 2, 2 * p * r / (p + r)))
print()
print("which one you optimise is a business decision, not a modelling one:")
print(" a spam filter wants precision -- a false alarm loses real mail.")
print(" a cancer screen wants recall -- a miss is far worse than a recheck.")
Output
Check yourself
0 of 3
Answer without scrolling back up.
What happens to precision and recall as the threshold falls?
A lower threshold flags more cases, so more real positives are caught (recall up) but the flagged set fills with negatives (precision down). The threshold picks a point on the trade-off, it does not improve the model.
Why is F1 a harmonic rather than arithmetic mean?
Precision 1.0 with recall 0.01 averages arithmetically to a respectable 0.505 and gives an F1 of 0.0198. The harmonic mean refuses to be gamed by a degenerate model.
Why is accuracy misleading when 1% of cases are positive?
Accuracy measures the class balance more than the model. Precision and recall would both be zero, which is the honest description of that model.
Cheat sheet
Precision, Recall and F1
Build a confusion matrix, then adjust the threshold and watch precision trade against recall while F1 tries to balance them both.
Ashish Jangra builds and maintains VizLearn. Every module here is written and the visualisation behind it hand-built, so the numbers in a readout come from the same code that draws the picture. Corrections are genuinely welcome and get priority over everything else — if a page states something wrong, or an animation misrepresents what the algorithm does, get in touch.