Why evaluation is the hardest part
You have eight sessions of detectors - statistical, rolling, distance, isolation, one-class, time-series, deep. Tonight is the referee. On rare events, the metric everyone reaches for first is worse than useless: it actively rewards a detector for doing nothing. So we throw accuracy out and build the scoreboard that survives a 1% base rate - precision, recall, F1, and the precision-recall curve summarised as PR-AUC. Then we pick the operating threshold on purpose, from the business cost of a miss versus a false alarm, and handle the one time-series wrinkle that trips people up: how to score a detection that lands inside, but not exactly on, a true anomalous segment. This is the same math the b3 live detector shows moving as you turn the sensitivity dial.
Accuracy is out - these three are in 6 min live
Recall the base-rate trap from b1: with anomalies under 1%, a detector that flags nothing scores 99%+ accuracy and catches zero. So accuracy never gets a vote. The honest three come from the confusion matrix on the positive (anomaly) class alone: precision asks, of the days you flagged, how many were real; recall asks, of the real anomalies, how many you caught; F1 is their harmonic mean, the single number that punishes a detector for being lopsided.
LiveThe four cells, and why F1 not accuracy3 min▶
Count four things against the labels, and notice what each metric ignores:
- TP flagged and real · FP flagged but normal (the false alarm) · FN real but missed (the costly one) · TN normal and left alone.
- Precision = TP / (TP + FP) - the false-alarm side. Low precision is what causes alert fatigue: the team stops trusting the pager.
- Recall = TP / (TP + FN) - the miss side. Low recall is the fraud that slipped through, the outage nobody paged on.
- F1 = 2PR / (P + R) - the harmonic mean, so a detector cannot win by acing one and tanking the other. Accuracy leans on TN, and TN is enormous and boring here, which is exactly why it lies.
Extreme imbalance is the normal case, not an edge case. Card fraud runs near 0.1%, hardware failures far rarer. With 999 normal to 1 anomaly, one lucky true catch amid a flood of false alarms still looks fine to accuracy. Precision and recall report the flood; F1 refuses to hide it. Always report the base rate next to the score, so a reader can judge whether the number is impressive or trivial.
The precision-recall curve and PR-AUC 5 min live
Most detectors do not output a yes or no - they output a score (isolation-forest anomaly score, seasonal residual size, LOF value). Every threshold you could set on that score gives one precision and one recall. Sweep the threshold from strict to loose and you trace the precision-recall curve: high precision and low recall on the left, sliding to high recall and low precision on the right. Its area, the PR-AUC (average precision), is the single number that summarises the detector across all thresholds - and on heavy imbalance it is the honest one, not ROC-AUC.
Self-studyWhy PR-AUC beats ROC-AUC on heavy imbalance2 min read▶
Both curves sweep a threshold, but they measure different things:
- ROC plots recall against the false-positive rate, FP / (FP + TN). With a giant normal class, TN is enormous, so even thousands of false alarms barely move the false-positive rate. ROC-AUC stays flatteringly high while the pager screams.
- PR plots precision against recall. Precision has FP in its denominator without the TN cushion, so every false alarm shows up. The curve, and PR-AUC, react to exactly the failure you care about.
- The random-chance floor also differs: for ROC it is a fixed diagonal; for PR it is the base rate, so a PR-AUC of 0.4 on a 1% base rate is a genuinely strong detector, not a weak one. Judge PR-AUC relative to the base rate.
Precision, recall, F1, then the whole PR curve ★ 12 min · everyone builds
Compute the three metrics by hand for one set of flags, then feed a continuous anomaly score to sklearn and get the entire precision-recall curve and PR-AUC.
Rebuild the labeled Lumen series so the notebook runs standalone.
From a fixed detector's flags, count TP/FP/FN and compute precision, recall, F1 from scratch.
Take an IsolationForest anomaly score and sweep every threshold with precision_recall_curve.
Summarise it with average_precision_score (PR-AUC) and compare it to the base rate.
Point-adjustment: scoring a segment, not a point 5 min live
Time-series anomalies come in segments - an outage lasts an hour, a bot surge runs for a run of days. If your detector flags the middle of a true anomalous segment but not its exact first point, point-wise scoring calls the rest misses, which feels unfair: you did catch the incident. The common convention, point-adjustment, fixes this: if any point inside a true segment is flagged, the whole segment counts as detected. It is standard in time-series anomaly papers - and it can quietly inflate your scores, so use it with your eyes open.
Self-studyUse it, but guard against the inflation2 min read▶
Point-adjustment is the near-universal convention in time-series anomaly benchmarks, and it does encode a real truth: catching an incident anywhere inside its window usually means the on-call team is paged in time. But the failure mode is sharp:
- The longer the segment, the bigger the free lunch. One flagged point turns a 100-point outage into a perfect catch. A detector that fires almost at random can score deceptively well.
- Guardrails - report point-wise scores alongside; require the hit to fall within a delay budget (paged fast enough to matter); or cap the credit per segment. Never publish point-adjusted numbers on their own.
- When you compare detectors, hold the scoring convention fixed. A model that looks better only under point-adjustment may just be luckier at landing one point in long segments.
Implement point-adjustment and watch it inflate ★ 8 min · build your own
Expand the labels into segments, mark a segment caught if any point inside it was flagged, and score both ways side by side. The gap you see is the inflation you must always disclose.
Write segments to find contiguous runs of anomaly labels.
Write point_adjust to flag a whole true segment when any point in it is flagged.
Score point-wise and point-adjusted with the same function and compare recall and F1.
This is the meter behind the b3 live detector. When you slide its sensitivity and watch precision and recall trade off, you are walking the precision-recall curve by hand, one threshold at a time. Everything tonight is what those two live meters mean. And the honest habit is the same at every scale: quote precision, recall, F1, PR-AUC, the base rate, and your scoring convention together - a number without its context is how detectors get oversold.
Try it yourself - this week ◐ 30-45 min total
- Compute precision, recall, and F1 from scratch for two of your detectors, and confirm they match sklearn's
precision_recall_fscore_support. - Build the full precision-recall curve from an IsolationForest or seasonal-residual score and read off the threshold that gives you 90% recall - note the precision you pay for it.
- Compute both PR-AUC and ROC-AUC on the same score and see how much rosier ROC looks. Explain why to a teammate.
- Run the point-adjustment scorer and quantify the inflation on the collective segment. Add a delay-budget guardrail and see the score come back down.
- Optional: skim the NAB scoring methodology and note how it rewards early detection inside a window - a cousin of point-adjustment.
Sources covered (cited)
Taught from the anomaly-detection canon. This session covers:
Three questions before you go 🎯 ◐ 90 seconds
1 · Why is PR-AUC preferred over ROC-AUC on heavily imbalanced anomaly data?
With a giant TN, ROC-AUC stays high even amid many false alarms. Precision has no TN cushion, so the PR curve and PR-AUC react to the failure you actually care about.
2 · How should you choose the operating threshold on the PR curve?
The threshold is a business decision, not a default. If a miss is far costlier than a false alarm, move toward recall; if the team is drowning in false alarms, move toward precision.
3 · What is the main caveat of point-adjustment?
The longer the segment, the bigger the free lunch - one hit can score a 100-point outage as a perfect catch. Report point-adjusted next to point-wise, never alone.