learn-anomaly-detection-with-phoebe / Builder session 1 of 10
Learn Anomaly Detection with Phoebe · Builder track · Session 1 of 10

Anomaly foundations: the points that do not belong

Fraud, outages, defects, intrusions - every one is a point that does not fit the pattern. This session sets up the running series we hunt anomalies in, our skincare brand Lumen's daily web sessions, defines the three kinds of anomaly you will chase all track, confronts the base-rate problem that makes rare events so slippery, and ships the first detector: a plain z-score baseline, scored the honest way.

🟢 Builder track Practitioners: analysts · data scientists · engineers Python 3.10+ · a notebook Start here
0-3 · Welcome 3-18 · Anomalies + the base rate 18-42 · Build-along: series + baseline 42-45 · Q&A
Part 0

How this track works

Ten hands-on sessions, one running series: Lumen, whose daily website sessions carry a weekly rhythm - and, hidden inside, a bot-driven spike, an outage-driven drop, a contextual dip, and a sustained odd run. You will hunt those with every family of detector in real Python - statistical, distance and density, isolation, one-class, time-series, and a look at deep methods - then learn to measure honestly, serve a detector, and keep it from crying wolf. Tonight lays the foundation: what an anomaly actually is, why rare events break your intuition, and the baseline detector every later method must beat. A running note: most real detection is unsupervised, labels are scarce, and accuracy is a liar on rare events - so we measure with precision and recall from day one.

Live - presented in session Self-study - read after class ★ Run it now (Python) Sources covered (cited)
★ What you walk out with today The labeled Lumen series built in pandas with four injected anomalies, a clear grip on the three anomaly types (point, contextual, collective), the base-rate problem that makes accuracy meaningless here, and a working z-score baseline detector scored with precision and recall - the honest line every model in this course has to beat.
Part 1 · covers the Chandola et al. taxonomy

Three kinds of anomaly 6 min live

Not every anomaly looks the same, and the type decides which detector can see it. The canonical survey (Chandola, Banerjee & Kumar, 2009) splits them into three: a point anomaly stands out on its own, a contextual anomaly is only odd for its context, and a collective anomaly is a run of points that together are wrong.

One series, three kinds of odd Point stands out on its own Contextual only odd for its context Collective a run that is wrong together
🔍 Click to zoom - point, contextual, and collective anomalies
LiveWhy the type decides the method3 min▶

The type is not academic - it tells you which detector can even see the anomaly:

  • Point - a single value far from the rest. A global z-score or IQR catches these easily. The bot spike in Lumen is a point anomaly.
  • Contextual - a value that is normal in the whole dataset but wrong for its context (a weekday sitting at a weekend-low level). Global methods miss it; you must remove the seasonal context first.
  • Collective - a sequence that is individually plausible but collectively abnormal (a sustained, unexplained run). Needs methods that look at windows, not single points.
Real world

Fraud is usually contextual or collective. A $500 purchase is not a point anomaly - plenty of people spend that. It is anomalous in context: this card, this hour, this location, after this sequence of small tests. That is why simple threshold rules miss real fraud, and why we spend this whole course past the global z-score.

Part 2 · the rare-event trap

Why accuracy lies 5 min live

Anomalies are rare by definition - often well under 1% of the data. That rarity breaks the metric everyone reaches for first. A detector that flags nothing at all is 99.5% accurate and completely useless. This is the base-rate problem, and it is why we never judge a detector by accuracy.

1000 days: 995 normal, 5 anomalies "Flag nothing" detector 99.5% accuracy - and useless It caught 0 of 5 anomalies. Accuracy rewarded it for ignoring the whole problem. Precision of the days you flagged, how many were real? Recall of the real anomalies, how many did you catch? F1 the balance of the two - the number that matters On rare events, precision and recall are the scoreboard. Accuracy is not invited.
🔍 Click to zoom - the base-rate problem, and the metrics that survive it
Self-studySupervised, semi-supervised, or unsupervised?2 min read▶

How much labelled truth you have decides the whole approach:

  • Unsupervised - no labels; assume anomalies are rare and different, and score how much each point stands out. This is the common case, and most of this course.
  • Semi-supervised - you have a clean sample of normal data only; learn its shape and flag departures (one-class methods, b6).
  • Supervised - you have labelled anomalies. Rare and precious, and heavily imbalanced - a classification problem with special care (b9). Real labels usually arrive late, via investigation.

Our Lumen series is labelled only so we can measure honestly. In production you would rarely have those labels up front.

Demo 1 of 2

Build the labeled Lumen series ★ 12 min · everyone builds

Construct the running series and its ground-truth labels so every later detector can be scored.

Build a daily sessions series with a weekly rhythm on a datetime index.

Inject four anomalies: a point spike, a point drop, a contextual dip (a weekday at a weekend-low level), and a collective run.

Record the ground-truth anomaly indices in a label vector - this is what precision and recall are measured against.

Plot it. See how the point anomalies jump out and the contextual one hides in plain sight.

★ Run it now (Python) - the labeled seriesimport pandas as pd, numpy as np idx = pd.date_range("2026-01-01", periods=90, freq="D") season = np.array([30,42,48,40,22,-95,-110]) # weekday shape i = np.arange(90) y = 900 + 1.2*i + season[i % 7] + 10*np.sin(i*1.7) + 7*np.cos(i*0.6) y = y.astype(float) truth = [20, 45, 63, 70, 71, 72] # ground-truth anomalies y[20] += 430 # point spike (bot surge) y[45] -= 380 # point drop (outage) y[63] = y[63] - season[63 % 7] + season[6] - 40 # contextual dip (weekday at weekend level) y[[70,71,72]] += [175,190,170] # collective run s = pd.Series(np.round(y), index=idx, name="sessions") label = pd.Series(0, index=idx); label.iloc[truth] = 1 print(s.head(), "\nanomalies:", label.sum(), "of", len(label), f"({label.mean():.1%} base rate)")
Labels are for measuring, not for cheating We inject and record the anomalies only so we can compute precision and recall. The detectors themselves never see label - they run unsupervised on s. Keep that wall up, or you will fool yourself.
Demo 2 of 2

Ship the z-score baseline ★ 8 min · build your own

Before any clever detector, build the baseline it has to beat. A global z-score flags any day more than three standard deviations from the mean. It is three lines, it catches the obvious point anomalies, and it will completely miss the contextual one - which is exactly the lesson.

Compute the z-score of every day against the global mean and standard deviation.

Flag days with |z| above 3, and score precision, recall, and F1 against the labels.

Note what it misses - in b3 you will watch a seasonal detector catch the contextual anomaly this one cannot see.

★ Run it now (Python) - z-score baseline + scoringimport numpy as np z = (s - s.mean()) / s.std() flags = set(np.where(np.abs(z) > 3)[0]) truth_set = set(truth) tp = len(flags & truth_set); fp = len(flags - truth_set); fn = len(truth_set - flags) precision = tp / (tp + fp) if tp + fp else 0 recall = tp / (tp + fn) if tp + fn else 0 f1 = 2*precision*recall / (precision + recall) if precision + recall else 0 print(f"caught {tp}/{len(truth_set)} precision {precision:.2f} recall {recall:.2f} F1 {f1:.2f}") # the global z-score catches the spike and drop, and misses the contextual dip
Real world

Never skip the baseline. A three-sigma rule is the "just show the bestsellers" of anomaly detection - shockingly serviceable, and the honest bar. If your isolation forest or autoencoder cannot beat a z-score on F1 (b9), it is not earning its complexity. And note the trap you just felt: the z-score's own huge outliers inflate its standard deviation, blunting it against the smaller anomalies. Robust methods (b2) fix exactly that.

Homework

Try it yourself - this week ◐ 30-45 min total

Source material

Sources covered (cited)

Taught from the anomaly-detection canon. This session covers:

✓Chandola, Banerjee & Kumar (2009), "Anomaly Detection: A Survey," ACM Computing SurveysParts 1-2 · the three anomaly types, supervised/unsupervised framing
◐Numenta Anomaly Benchmark (NAB)Part 2 · why accuracy fails on rare events
Check yourself

Three questions before you go 🎯 ◐ 90 seconds

1 · A weekday whose traffic sits at a normal weekend-low level is which kind of anomaly?

The value is perfectly normal globally, but wrong for its context (a weekday). Global detectors miss it; you must remove the seasonal context first.

2 · Why is accuracy a bad metric for anomaly detection?

The base-rate problem: with anomalies under 1%, "flag nothing" is 99%+ accurate and useless. Precision and recall are the honest scoreboard.

3 · Why build the z-score baseline first?

A three-sigma rule is a serviceable baseline. If a complex model cannot beat it on F1, it is not earning its complexity - and it reveals why robust methods (b2) are needed.

Builder session 1 cheat sheet · pin this

Anomalya point that does not fit the pattern. Behind fraud, outages, defects, and intrusions.
Pointstands out on its own. Global z-score / IQR catch these.
Contextualnormal in value, wrong for its context. Deseasonalize first, or you miss it.
Collectivea run that is wrong together. Needs window-based methods.
Base-rate trapanomalies are rare, so accuracy lies. "Flag nothing" scores 99%+ and catches zero.
Precision / recall / F1of flags, how many real; of reals, how many caught; and their balance. The real scoreboard.
Usually unsupervisedlabels are scarce and late. Score how much each point stands out; treat labels as precious.
Next sessionb2 - statistical detectors: z-score, 3-sigma, IQR, and robust MAD.