One example, two questions
A spam filter looks at 100 emails, of which 20 are spam. It flags 15 emails as spam, and 12 of those really are spam.
- Precision = correct flags ÷ all flags = 12 ÷ 15 = 80%. When the filter says spam, it’s right 80% of the time.
- Recall = correct flags ÷ all real spam = 12 ÷ 20 = 60%. The filter catches 60% of the spam; the other 8 reach the inbox.
The two numbers describe different mistakes. The 3 wrongly flagged emails (false positives) lower precision. The 8 missed spam emails (false negatives) lower recall.
The trade-off
Most models give a score, and a threshold decides what counts as a yes. Lower the threshold and the model flags more: recall goes up, but more of the flags are wrong, so precision goes down. Raise it and the opposite happens. You can’t usually have both at 100%, so you choose where to sit based on what each mistake costs.
Which one matters more?
- Favor precision when a false alarm is expensive. A spam filter that hides a real invoice, or a fraud system that blocks a good customer’s card. You’d rather miss some cases than act on wrong ones.
- Favor recall when missing a case is expensive. Screening for a disease, finding defective parts, or spotting customers about to leave. A false alarm costs a second look; a miss costs much more.
- Need both? Use the F1 score, which combines them, or set a minimum for one and maximize the other, for example “at least 98% precision, as much recall as possible.”
Why not just use accuracy?
When one class is rare, accuracy hides everything that matters. If 1% of transactions are fraud, a model that never flags anything is 99% accurate, with 0% recall. Precision and recall look only at the rare class, which is usually the one you care about.
In Python
CodePrecision and recall with scikit-learn
from sklearn.metrics import precision_score, recall_score, classification_report
y_true = [1, 1, 1, 0, 0, 0, 0, 1, 0, 0] # 1 = spam
y_pred = [1, 1, 0, 0, 1, 0, 0, 1, 0, 0]
print("Precision:", precision_score(y_true, y_pred)) # 3 of 4 flags were right: 0.75
print("Recall: ", recall_score(y_true, y_pred)) # 3 of 4 spam emails found: 0.75
print(classification_report(y_true, y_pred))