Where we are
In b1 we built the labeled Lumen series and shipped a z-score baseline that caught the giant spike and drop but missed everything subtler. Tonight we stay in the world of global thresholds - a single cut line for the whole series - but we make it honest. The plain z-score has a self-inflicted wound: the big anomalies it is meant to catch inflate its own standard deviation, and that fattened band swallows the moderate anomalies whole. This is masking. The fix is to build thresholds on statistics the outliers cannot move - quartiles and the median - which gives us the IQR fences and the robust MAD rule. Three detectors, one line of defence, and a clear rule for when each one fits.
Three ways to draw the line 7 min live
All three detectors flag a point that sits too far from the centre. They differ in how they measure the centre and the spread - and that difference is everything, because one uses statistics the outliers can drag around, and two do not.
LiveThe three detectors, and when each fits3 min▶
- z-score / three-sigma - flag
|x − mean| / std > 3. Fast, assumes a roughly bell-shaped spread. Fatal flaw: the mean and std are computed from data that includes the anomalies, so big outliers inflate both and the rule masks the moderate ones. Use only when you are confident outliers are few and small, or as the baseline to beat. - IQR / Tukey fences - flag anything below
Q1 − 1.5·IQRor aboveQ3 + 1.5·IQR, whereIQR = Q3 − Q1. Quartiles ignore the extreme tails, so the fences do not widen when an outlier appears. A solid, distribution-light default. - robust MAD - modified z-score
0.6745·(x − median) / MAD, whereMADis the median of|x − median|; flag|modified z| > 3.5. The median and MAD have the highest breakdown point of the three - roughly half the data would have to be corrupt to move them - so this is the most outlier-resistant threshold.
Server latency dashboards learned this the hard way. A plain mean+3σ alert on p99 latency goes quiet during the exact incidents it should catch: one monster spike lifts the mean and fattens the band, so the sustained-but-smaller degradation that follows sits comfortably inside it. Teams that switched to median+MAD or IQR fences started catching the slow bleeds. Same data, robust statistic, very different alerts.
Masking and swamping 5 min live
The plain z-score does not just miss subtle anomalies by bad luck - it hides them by construction. Because a giant outlier inflates the standard deviation, the three-sigma band grows so wide that moderate anomalies fall inside it. Strip the giant outlier out and the band snaps back, and the hidden anomaly suddenly crosses the line. This is masking; its mirror image, swamping, is when outliers stretch the band so far that normal points get wrongly flagged.
Self-studyWhy 1.5, 3, and 3.5? The magic constants2 min read▶
The thresholds are conventions, not laws - tune them to your precision/recall need:
- 3σ - for a normal distribution about 99.7% of data sits inside ±3σ, so ~0.3% is flagged. If your data has fat tails, expect more false alarms.
- 1.5·IQR - Tukey's original choice for a "boxplot outlier". 3·IQR marks "far out" points. Lower it to flag more, raise it to flag less.
- 0.6745 and 3.5 -
0.6745rescales MAD so that, on normal data, the modified z-score matches an ordinary z-score. Iglewicz and Hoaglin recommend flagging above 3.5. All three constants are levers on the same alert-fatigue trade-off.
Three detectors, scored side by side ★ 12 min · everyone builds
Rebuild the Lumen series, run all three thresholds, and score each against the truth. Watch the robust pair beat the plain z-score on the same data.
Rebuild the labeled series from b1 so the notebook runs standalone.
Compute z-score flags, IQR / Tukey flags, and MAD modified-z flags.
Print each detector's flagged days and its precision, recall, and F1 against truth.
Watch masking happen ★ 8 min · build your own
Now prove the flaw directly. The collective-run days sit hidden inside the z-score band. Remove the two giant point anomalies that were inflating the standard deviation, recompute, and watch the hidden days climb across the threshold - value unchanged, only the band moved.
Print the z-score of the collective-run days with the giant spike and drop still in the series - all below 3, all masked.
Drop the two giant point anomalies and recompute the z-score.
See the standard deviation shrink and days 71 and 72 cross the threshold - the definition of masking.
This is why "just use a z-score" quietly fails in production. The loudest anomaly in your window sets the threshold for every other point, so the biggest incident actively conceals the medium ones around it. You cannot see masking by staring at the output - a masked anomaly leaves no trace. You catch it by defaulting to robust statistics (MAD, IQR) or by removing known outliers before you fit the threshold. When in doubt, reach for the median.
Try it yourself - this week ◐ 30-45 min total
- Run all three detectors and confirm the precision/recall/F1 you get matches the commented output.
- Sweep the z-score cutoff from 2.0 to 4.0 in steps of 0.25 and plot recall against the number of false flags. Where would you set it, and why?
- Change the MAD cutoff from 3.5 to 3.0 and to 4.0. Watch precision and recall trade off - this is the alert-fatigue dial.
- Reproduce masking on your own: add a second giant spike to the series, confirm a previously caught anomaly disappears, then remove both spikes and watch it return.
- Optional: skim the scikit-learn "Novelty and Outlier Detection" user guide section on robust covariance to preview b6.
Sources covered (cited)
Taught from the statistical-detection canon. This session covers:
statsmodels / scipyParts 1-2 · z-score, IQR / Tukey fences, robust MAD in practiceThree questions before you go 🎯 ◐ 90 seconds
1 · What is the fatal flaw of the plain z-score / three-sigma rule?
Masking: the mean and std are computed from data that includes the anomalies, so a giant outlier fattens the ±3σ band until the moderate anomalies fall inside it.
2 · The Tukey / IQR fences flag a point outside which range?
The fences are built on quartiles, which ignore the extreme tails - so a lone outlier cannot widen them the way it widens a standard deviation.
3 · Why is the MAD-based modified z-score the most outlier-resistant of the three?
Median and MAD barely budge when a few points explode, so the threshold built on them stays honest - unlike the mean and std, which any single giant outlier can drag.