Which Score Actually Matters? A Plain-English Guide to Precision, Recall, and the Rest
You just finished training your first machine learning model. You check the accuracy — 99%. You feel like a genius. You show it to your boss, expecting a promotion, but they look at the data and frown. “This model is useless,” they say.
How can 99% accuracy be useless? In this guide, we’ll make sense of the confusing numbers in your classification report. We’ll see why accuracy often misleads — and how to pick the one number that actually matters for your specific job.
1. The Hospital Test Trap: Why 99% Accuracy Can Be a Lie
Imagine you’re building a tool to detect a very rare disease. In a town of 1,000 people, only 10 actually have it. The other 990 are perfectly healthy.
If I write a dumb piece of code that simply tells every person, “You are healthy,” how accurate am I?
I’m 99% accurate! I got 990 people right and only 10 wrong. Yet I failed at the only job I had. I didn’t find a single sick person. This is the Accuracy Paradox. When your data is lopsided — what we call imbalanced — accuracy is a terrible way to measure success.
Let’s run it in Python.
import numpy as np
from sklearn.metrics import accuracy_score
# 990 healthy people (0) and 10 sick people (1)
actual_labels = [0] * 990 + [1] * 10
# A 'dumb' model that just predicts '0' (healthy) for everyone
dumb_predictions = [0] * 1000
print(f"Accuracy Score: {accuracy_score(actual_labels, dumb_predictions) * 100}%")
The code prints 99.0%. The model is “right” almost all the time, but it’s completely useless — a 0% success rate at finding the disease.
2. Precision: The ‘Don’t Cry Wolf’ Metric
Accuracy wasn’t enough, so we need better tools. The first is Precision.
Take a spam filter. If it marks an important email from your mom as spam, you’ll be annoyed. Saying “yes, this is spam” when it actually isn’t is a costly mistake.
Precision asks: “Of all the times I said this was a win, how many were actually wins?”
High precision means you’re careful. You don’t cry wolf unless you’re sure.
# Let's say we have 10 emails. 5 are spam, 5 are not.
actual_spam = [1, 1, 1, 1, 1, 0, 0, 0, 0, 0]
# Our model predicts 3 are spam, and it got all 3 right.
predicted_spam = [1, 1, 1, 0, 0, 0, 0, 0, 0, 0]
from sklearn.metrics import precision_score
prec = precision_score(actual_spam, predicted_spam)
print(f"Precision: {prec}")
The result is 1.0 (or 100%). Every time the model flagged an email as spam, it was right. It missed some actual spam (the other 2), but it never cried wolf on a good email.
3. Recall: The ‘No Stone Left Unturned’ Metric
Back to the hospital. When you’re screening for cancer, missing a sick patient is the worst outcome. You’d rather tell a healthy person “we need to double-check this” — a false alarm — than tell a sick person “you’re fine” and send them home.
Recall answers: “Of all the people who were actually sick, how many did I manage to find?”
Here’s the hard part. Precision and Recall usually pull in opposite directions. Push for high recall — finding every sick person — and you’ll flag some healthy people by mistake, dragging precision down.
# 10 people are actually sick
actual_sick = [1] * 10 + [0] * 10
# Model is 'scared' and flags almost everyone as sick just to be safe
predicted_sick = [1] * 10 + [1] * 8 + [0] * 2
from sklearn.metrics import recall_score
rec = recall_score(actual_sick, predicted_sick)
print(f"Recall: {rec}")
The result is 1.0. The model found 100% of the sick people. But it also flagged 8 healthy people as sick. Its precision would be very low, but its recall is perfect. In a hospital, this is often exactly what we want.
4. F1-Score: The ‘Middle Ground’ for Busy People
What if you want a balance? You don’t want to cry wolf, but you also don’t want to miss the needles in the haystack. That’s where the F1-Score comes in.
You might think we should just average Precision and Recall. But imagine a model with 100% Recall and 0% Precision. A simple average would give it a 50%. A model with 0% precision is useless.
The F1-Score uses the harmonic mean instead. It punishes extreme values. If either your Precision or your Recall is terrible, the F1-Score will crash.
from sklearn.metrics import f1_score, precision_score, recall_score
# Case A: Balanced model (0.8 Precision, 0.8 Recall)
y_true_a = [1] * 10 + [0] * 10
y_pred_a = [1] * 8 + [0] * 2 + [1] * 2 + [0] * 8
prec_a = precision_score(y_true_a, y_pred_a)
rec_a = recall_score(y_true_a, y_pred_a)
f1_a = f1_score(y_true_a, y_pred_a)
# Case B: Extreme case (perfect Recall, near-zero Precision)
y_true_b = [1] + [0] * 99
y_pred_b = [1] * 100
prec_b = precision_score(y_true_b, y_pred_b)
rec_b = recall_score(y_true_b, y_pred_b)
f1_b = f1_score(y_true_b, y_pred_b)
print(f"Case A — Precision: {prec_a}, Recall: {rec_a}, Simple Avg: {(prec_a+rec_a)/2}, F1: {f1_a}")
print(f"Case B — Precision: {prec_b}, Recall: {rec_b}, Simple Avg: {(prec_b+rec_b)/2}, F1: {f1_b}")
Case A prints Precision: 0.8, Recall: 0.8, Simple Avg: 0.8, F1: 0.8 — a genuinely balanced model, and the F1-score agrees with the simple average because precision and recall already match.
Case B is the extreme case the intro warned about: precision of 0.01, recall of a perfect 1.0. A simple average makes that look like a coin-flip 50.5% model (Simple Avg: 0.505). The F1-score isn’t fooled — it prints F1: 0.019801980198019802, about 2%. That’s the harmonic mean doing its job: it crashes toward whichever number is worse, so a terrible precision can’t hide behind a great recall (or vice versa).
5. AUC-ROC: How Good is the Model at Sorting?
Most models don’t just say “Yes” or “No.” They give you a probability — “85% chance this is a cat,” say.
AUC-ROC measures how well a model ranks things. Give it one random sick person and one random healthy person. What’s the probability it assigns the sick person a higher “danger score”?
- 0.5 means the model is guessing — a coin flip.
- 1.0 means perfect sorting.
from sklearn.metrics import roc_auc_score
actual = [0, 0, 1, 1]
probabilities = [0.1, 0.4, 0.35, 0.8] # Note: the 3rd item is ranked lower than the 2nd!
auc = roc_auc_score(actual, probabilities)
print(f"AUC Score: {auc}")
The score here is 0.75. Not perfect: it gave one healthy person (0.4) a higher score than a sick person (0.35). AUC tells you how much to trust those probability gut calls.
6. The Cheat Sheet: Which One Should You Use?
So, which number should you tell your boss? Here’s the breakdown:
- Use Precision when the cost of being wrong is high. (Example: you don’t want to fire a good employee by mistake.)
- Use Recall when the cost of missing something is high. (Example: you don’t want to miss a fraudulent credit card transaction.)
- Use F1-Score when you want a balanced model and your classes are imbalanced.
- Use AUC-ROC when you need to rank items (like a recommendation list) rather than give a Yes/No answer.
- Use Accuracy when your classes are roughly balanced and a false positive costs about the same as a false negative; otherwise report precision and recall separately.
Here’s one final classification report that pulls it all together:
from sklearn.metrics import classification_report
y_true = [0, 0, 0, 1, 1, 1]
y_pred = [0, 0, 1, 1, 1, 1]
print(classification_report(y_true, y_pred))
When you see this table, start with the Recall for the ‘1’s if you’re worried about missing things. Check the Precision for the ‘1’s if false alarms are the bigger concern. For a general read on whether the model is working, look at the F1-score.
Now you can walk into that meeting and explain why your 99% accuracy was misleading—and what the real story is.
Check Your Understanding
Questions below move from simple recall up to open-ended design, roughly following Bloom’s Taxonomy.
Remember What question does Precision answer, and what question does Recall answer, in the article’s own phrasing?
Understand In your own words, explain why a simple average of Precision and Recall would give a useless model (100% Recall, 0% Precision) an unearned 50% score, and why the F1-Score’s harmonic mean avoids that problem.
Apply Using the article’s cheat sheet, which metric would you prioritize for a credit card fraud detector where missing a fraudulent transaction is far more costly than flagging a legitimate one for review?
Analyze The article’s AUC-ROC example scores 0.75 because the model ranked a healthy person (0.4) above a sick person (0.35). Walk through why AUC-ROC cares about this relative ranking between one sick and one healthy person, rather than caring about the absolute probability values (like whether 0.35 is “low enough” to count as healthy).
Evaluate The article’s cheat sheet conditions Accuracy on two things: classes that are roughly balanced, and a False Positive costing about the same as a False Negative. Critique the word “roughly” — even with a perfectly 50/50 class split, can accuracy still mislead you if the cost of a False Positive and a False Negative are very different for the business, even though the class counts are equal? What does that imply about relying on class balance alone?
Create Design a metric-selection justification for a new scenario: a model that screens loan applications, where a False Positive (approving a loan that defaults) costs the bank $50,000 on average, and a False Negative (rejecting a good applicant) costs about $500 in lost interest. Using the article’s Precision/Recall framing, explain which metric you’d optimize for and how you’d explain that choice to a non-technical loan officer.
Apply What You Learned
You’ve shipped a loan-screening classifier and the VP of Lending has called a stakeholder review. She sees 87% accuracy and asks, “Why isn’t this higher?” Write a 250–350 word memo that (a) explains why accuracy is the wrong number to fixate on for this problem, and (b) defends your choice of precision as the primary metric — given the article’s cost framing where a False Positive (approving a loan that defaults) costs the bank $50,000, while a False Negative (rejecting a good applicant) costs about $500 in lost interest.
Deliverable: A 250–350 word memo to the VP of Lending (non-technical). Include a subject line. Ground your argument in the article’s precision/recall framing — cite the “don’t cry wolf” logic for why precision fits the $50K cost asymmetry, and acknowledge at least one concrete tradeoff (what you sacrifice by optimizing precision over recall).
Rubric (every item must be present for a pass):
- ☐ Names precision as the primary metric and correctly maps the $50K False Positive cost to the article’s “don’t cry wolf” logic
- ☐ Explains why accuracy alone is misleading for this problem, referencing the article’s Accuracy Paradox (the 99%-on-10-sick-out-of-1000 example or equivalent reasoning)
- ☐ Uses at least two of these terms correctly in context: precision, recall, false positive, false negative, harmonic mean, AUC-ROC
- ☐ Acknowledges a concrete tradeoff of prioritizing precision (e.g., rejecting some good applicants, slower loan-approval throughput) rather than presenting it as a free lunch
- ☐ Written for a non-technical reader — no unexplained jargon; any metric name is defined in plain English on first use
Related articles
- Machine Learning Under review
Reference: Feature Engineering
A standalone lookup for feature engineering: pick the right encoder, scaler, derived feature, time-series construct, and distance metric for any model family.
- Machine Learning Under review
Learning Curves: How to Read Your Model's Mind to Fix Overfitting and Underfitting
Learn to read learning curves to diagnose overfitting and underfitting, tell high bias from high variance, and pick the right fix to boost your model.
- Machine Learning Under review
How Gradient Descent Actually Works — and the Variants That Make It Practical
Learn how gradient descent minimizes model error by feeling the slope of your loss function, and compare Batch, SGD, Mini-Batch, and Adam with plain Python.
- Machine Learning Under review
The Archer and the Target: Why Models Miss
Learn the bias-variance tradeoff through an archer analogy and hands-on Python examples that reveal how underfitting and overfitting shape model accuracy.
Looking for something else?
Search every article by title, summary or topic.