Classification evaluation is how you measure whether a model assigns the right label (or set of labels) for an input. In software terms: you want to quantify the failure modes (false alarms vs misses), pick an operating point (threshold), and prevent regressions when data/model changes.

Precision, Recall, and F1

Confusion matrix first

Everything starts from four counts:

Actual positiveActual negative
Predicted positiveTPFP
Predicted negativeFNTN
  • TP: you flagged positive and it really was positive.
  • FP: false alarm.
  • FN: miss.
  • TN: correctly ignored.

The three formulas to remember

precision = TP / (TP + FP)
recall    = TP / (TP + FN)
F1        = 2 * (precision * recall) / (precision + recall)
  • Precision: from predicted positives, how many are truly positive.
  • Recall: from real positives, how many you found.
  • F1: one score that is high only when both precision and recall are high.

Memory hook:

  • Precision is hurt by FP false alarms.
  • Recall is hurt by FN misses.

Threshold tradeoff

flowchart LR
  L[Low threshold] --> M[More predicted positives]
  M --> R1[Recall usually up]
  M --> P1[Precision usually down]
  H[High threshold] --> F[Fewer predicted positives]
  F --> R2[Recall usually down]
  F --> P2[Precision usually up]

Real world examples

Content moderation:

  • Low threshold catches more unsafe posts, but blocks more safe posts.
  • High threshold blocks fewer safe posts, but lets more unsafe posts pass.

Fraud detection:

  • High recall means fewer fraud cases slip through.
  • High precision means fewer legit users get flagged.

Worked example

Binary classifier on 100 cases:

TP = 32
FP = 8
TN = 50
FN = 10
precision = 32 / (32 + 8)  = 0.80
recall    = 32 / (32 + 10) = 0.76
F1        = 2 * (0.80 * 0.76) / (0.80 + 0.76) = 0.78

Same model family at two thresholds:

ThresholdTPFPFNPrecisionRecall
0.309060100.600.90
0.805510450.850.55

Multi-class Averaging

When extending precision/recall to multi-class problems, the averaging method changes the number you see:

MethodFormulaWhen to Use
MacroAverage metric across classes equallyAll classes are equally important regardless of size (e.g., rare disease detection)
MicroAggregate TP/FP/FN globally, then computeOverall correctness matters most, classes are roughly balanced
WeightedAverage weighted by class support (count)Classes have different sizes and you want proportional representation

Decision rule: use macro-average when minority classes matter (medical, safety). Use micro-average for balanced datasets or when you want a single aggregate number. Use weighted-average for reporting to stakeholders who think in terms of “percentage of all predictions correct.”

Pitfalls

F1 hides asymmetric failures — an F1 of 0.78 could be precision 0.95 / recall 0.66 or precision 0.66 / recall 0.95. These have completely different operational impact: a fraud model with recall 0.66 silently misses a third of fraud cases, while one with precision 0.66 floods reviewers with false alarms. Always report precision and recall separately alongside F1.

Comparing models at different thresholds — if Model A runs at threshold 0.3 and Model B at 0.7, comparing their precision/recall is meaningless. Fix the threshold policy first (e.g., “recall ≥ 0.95”), then compare precision at that fixed operating point. Better yet, compare PR-AUC or ROC-AUC for threshold-invariant comparison.

Optimizing a single metric — a spam filter optimized purely for precision (blocking only obvious spam) lets a large share of spam through. The same filter optimized purely for recall starts blocking legitimate emails. Neither is deployable. Always optimize under a constraint: “maximize precision subject to recall ≥ X” (or vice versa).

Class imbalance distortion — accuracy is misleading on imbalanced datasets. A model that always predicts “not fraud” on a dataset with 0.1% fraud rate achieves 99.9% accuracy but catches zero fraud. Use precision/recall/F1 (which ignore TN) or balanced accuracy. In production, track per-class metrics separately.

Questions

References