Guide

When the positive class is "anything weird" and labels are rare, treat the problem as unsupervised (or semi-supervised on "normal only" data). You still need an operating point. Unsupervised scores do not magically pick a useful alert volume.

Concept

An isolation forest isolates outliers in fewer random splits than normal points. Lower scores are more anomalous. contamination is not a ground-truth rate. It is a knob that forces a fraction of rows to be flagged.

The big idea

MethodIdeaFits
Statistical thresholdsFlag if z-score or quantile is extremeSimple metrics, seasonality-aware baselines
Isolation forestRandom partitions isolate outliers in fewer splitsTabular mixed features, scalable
One-class SVMBoundary around normal massSmaller datasets
AutoencodersHigh reconstruction error ⇒ anomalyHigh-dimensional / sensory data

Use z-scores / seasonal baselines when you have one well-understood metric (CPU, error rate). Use isolation forests when anomalies are combinations of many features. Use autoencoders when inputs are images, traces or wide sparse vectors and you already run neural training.

Setting contamination=0.01 because "we expect 1% anomalies" does not make the flags correct. It forces 1% of rows to be flagged even if the world is clean. Prefer scoring plus a capacity-based threshold, same spirit as classification evaluation.

Walking through a production shape

  1. Define a "normal" training window (for example last 28 days of healthy traffic).
  2. Fit isolation forest or seasonal baselines on that window only.
  3. Score new points. Alert above a threshold chosen so on-call sees about N alerts/day.
  4. Analysts label alerts for a week. Estimate precision. Adjust the threshold.
  5. Retrain on a rolling schedule. Watch for concept drift. Black Friday is not an anomaly if it happens every year — add calendar features or seasonality models.
Python
from sklearn.datasets import make_blobs
from sklearn.ensemble import IsolationForest

X, _ = make_blobs(n_samples=1000, centers=1, cluster_std=0.6, random_state=0)
iso = IsolationForest(n_estimators=200, contamination=0.01, random_state=0)
flags = iso.fit_predict(X)  # -1 anomaly, 1 normal
n_flagged = int((flags == -1).sum())
print("flagged", n_flagged, "of", len(X))

Output:

flagged 10 of 1000

contamination=0.01 forced about 1% of rows to be flagged. That is a capacity choice, not a discovery that 10 points are truly bad.

Budget analyst time to review flags. The metric that matters is precision at the alert volume on-call can handle.

DBSCAN's noise label is a cousin of this idea: sparse points are not a cluster. Isolation forest scales better on mixed tabular features.

Common mistakes

  • Treating contamination as the true anomaly rate. It is a quota.
  • Training the "normal" model on a window that already includes incidents. The incident becomes the baseline.
  • Alerting on Black Friday as a novelty every year. Put seasonality in the features.

Check yourself

  1. Isolation forest with contamination=0.01 on 1000 clean rows. About how many flags? Answer: About 10, because the knob forces 1% to be flagged.
  2. What should set the threshold if on-call can handle 20 alerts a day? Answer: The score cutoff that produces about 20 alerts a day, then measure precision on a labeled audit.

Key takeaways

  • Isolation forests and reconstruction errors flag anomalies. Thresholds still need human cost logic.
  • contamination is a quota, not a ground-truth rate.
  • Fit on a healthy window. Retrain on a rolling schedule. Watch seasonality.
  • Precision at a handleable alert volume is the metric that matters.

Further learning

Back to the map: unsupervised learning.

scikit-learn: ClusteringClustering of unlabeled data can be performed with the module sklearn.cluster. Each clustering algorithm comes in two variants: a class, that implements the fit method to learn the clusters on trai...scikit-learn