A different question
So far every detector has drawn a global line - a z-score band, a Tukey fence, a seasonal residual cutoff. Distance and density methods throw that away and reason locally: an anomaly is a point with no close company. Two ideas carry the session. First, kNN distance - score each point by how far its nearest neighbours are; anomalies sit in empty space. Second, the Local Outlier Factor (Breunig et al., 2000) - a point is anomalous if its local density is much lower than its neighbours' density, which lets it find outliers even when different regions of the data are packed at different tightness. Both are naturally multivariate: they shine when you have several features, so for a time series we build features first - value, a lag, rolling statistics - and let the geometry do the work.
How lonely is this point? 7 min live
The simplest neighbour-based score: measure the distance from each point to its k-th nearest neighbour, or the mean distance to its k nearest. Points deep inside a cluster have tiny distances; a point out in empty space has a large one. Sort by that score and the anomalies rise to the top.
LiveMultivariate by nature - and the dimensionality caveat3 min▶
Neighbour methods measure distance in feature space, so they earn their keep when a point is only anomalous across several features at once - a normal traffic volume at a normal hour but from an abnormal device mix. On a raw one-dimensional series they collapse back to something z-score-like, which is why we engineer features first:
- value - the raw session count for the day.
- lag - yesterday's value, so a sudden jump becomes a distance.
- rolling mean / std - the recent local level and volatility, so a point far from its own neighbourhood stands out.
The curse of dimensionality caveat: as you add features, distances between all points converge and "nearest" loses meaning - everything looks equidistant. Scale your features (distances are unit-sensitive) and keep the feature set lean. Distance methods are strongest in low-to-moderate dimensions.
Density, relative to your neighbours 5 min live
A global distance has one blind spot: real data is not uniformly dense. A point sitting in a naturally sparse region has a large kNN distance and looks anomalous - but it is perfectly normal for its neighbourhood. LOF fixes this by comparing each point's local density to the density of its neighbours. If yours is roughly the same as theirs, LOF ≈ 1 (normal); if yours is far lower, LOF ≫ 1 (anomalous). It is a ratio, so it adapts to whatever density each region happens to have.
Self-studyReading negative_outlier_factor_2 min read▶
scikit-learn's LocalOutlierFactor stores its scores in negative_outlier_factor_ after fit_predict. A few gotchas:
- The stored value is the negative LOF, so normal points sit near
-1and anomalies are more negative. Flip the sign to get the familiar LOF where higher = more anomalous. - By default it runs in outlier mode (fit and predict on the same data). For novelty detection - training on clean data, scoring new points - set
novelty=Trueand use.predict(). contaminationsets the flag rate. It is a precision/recall dial, not a fact about the world - pick it from your alert budget, not by wishful thinking.
Features + kNN distance ★ 12 min · everyone builds
Turn the one-dimensional Lumen series into a feature matrix, then score each day by its mean distance to its k nearest neighbours and check the top scores against the truth.
Build features: value, a one-day lag, and rolling mean and std over a week.
Scale the features, then compute each day's mean distance to its k nearest neighbours.
Flag the highest-scoring days and score precision, recall, and F1 against truth.
value in the hundreds would drown a roll_std in the tens - the detector would effectively see only one feature. StandardScaler puts every feature on the same footing. Forgetting it is the most common reason a distance detector "does not work".
LOF, and why local beats global ★ 10 min · build your own
Run LOF on the same feature matrix, then settle the argument: on a two-density example, watch a global kNN distance mis-flag a perfectly normal sparse point while LOF keeps it - and still catches the real outlier.
Fit LocalOutlierFactor on the Lumen features, read negative_outlier_factor_, flag, and score.
Build a toy dataset with a dense cluster and a sparse cluster plus one true outlier.
Compare a global kNN distance against LOF for the outlier and for a normal sparse-cluster point.
This is exactly the trap in mixed populations. Power users click ten times more than casual users - a naturally "sparse" region of behaviour. A global distance rule flags every power user as anomalous and floods the queue with false alarms, the fastest route to a muted alert. LOF asks the fairer question - "is this account odd for accounts like it?" - and reserves the flag for the genuinely strange. When your data has sub-populations of different density, prefer LOF.
Try it yourself - this week ◐ 30-45 min total
- Reproduce the kNN and LOF scores and confirm they match the commented output.
- Sweep
k(andn_neighbors) from 3 to 30. Watch precision and recall move - small k is jumpy, large k oversmooths. - Drop the rolling features and rerun with value + lag only. How much does the leaner feature set cost you, and why?
- Add three noise features of pure randomness to the matrix and rerun. Watch the curse of dimensionality erode the scores.
- Optional: read Breunig, Kriegel, Ng & Sander (2000), "LOF: Identifying Density-Based Local Outliers" - the paper that defined the local density ratio.
Sources covered (cited)
Taught from the density-based detection canon. This session covers:
NearestNeighbors, LocalOutlierFactor, novelty vs outlier modeThree questions before you go 🎯 ◐ 90 seconds
1 · What does the kNN-distance anomaly score measure?
Points deep in a cluster have small neighbour distances; a point out in empty space has a large one, so it rises to the top when you rank by the score.
2 · What does the Local Outlier Factor compare?
Because LOF is a density ratio, each region's own tightness becomes its baseline, so it flags a point only when it is sparse relative to its neighbours.
3 · When does LOF clearly beat a global kNN distance?
A naturally sparse-but-normal point has a large global distance and gets wrongly flagged; LOF's local ratio keeps it normal while still catching the true outlier.
Builder session 4 cheat sheet · pin this
StandardScaler before NearestNeighbors or LOF.