8 · LOF: local outlier factor
Local Outlier Factor compares each point's density to its neighbours' density — catching context-dependent anomalies that Isolation Forest might miss.
LOF measures how much MORE isolated a point is than its neighbours — catches outliers WITHIN dense regions that Isolation Forest might miss.
Without this:
Without LOF you miss local anomalies — points that look normal globally but are unusual in the context of their cluster.
Isolation Forest scores points globally — it asks how hard it is to isolate a point from the entire dataset. This works beautifully for global outliers (a point that is unusual everywhere), but misses local outliers: points that look perfectly normal from a global perspective but are unusual relative to their neighbourhood.
Imagine a dataset with two clusters — one very tight (100 near-identical transactions), one very loose (100 spread-out measurements). A point that falls on the edge of the tight cluster may be a suspicious local anomaly even though, globally, it is not as extreme as the scattered points in the loose cluster.
Local Outlier Factor (LOF) addresses this by computing a local density for each point and comparing it to the densities of its k nearest neighbours.
Key concepts:
-
k-distance(x): distance from point x to its k-th nearest neighbour.
-
Reachability distance:
reach_dist_k(x, y) = max(k-distance(y), dist(x, y))— a smoothed distance that prevents instability for very close pairs. -
Local Reachability Density (LRD): the inverse of the mean reachability distance to the k neighbours:
LRD_k(x) = 1 / (Σ_{y ∈ N_k(x)} reach_dist_k(x, y) / k)
High LRD = point is in a dense region. Low LRD = point is in a sparse region.
-
LOF score: ratio of the mean LRD of the k neighbours to the LRD of x itself:
LOF_k(x) = (Σ_{y ∈ N_k(x)} LRD_k(y) / k) / LRD_k(x)
- LOF ≈ 1 → point has similar density to its neighbours → inlier.
- LOF >> 1 → point is much less dense than its neighbours → outlier.
- LOF < 1 → point is denser than its neighbours (rare, occurs in cluster centres).
This local ratio is what separates LOF from global methods: a point in the loose cluster with LOF ≈ 1 is normal for that neighbourhood, even though it would look "outlier-ish" to a global scorer.
Python (in browser)
LOF on a dual-density dataset — the color encodes LOF score. Points near the tight cluster that are slightly too sparse for that neighbourhood are flagged, even though they are not global extremes.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
Side-by-side comparison — Isolation Forest tends to flag global extremes; LOF flags points whose local neighbourhood is significantly denser than the point itself, catching the local outliers near the tight cluster.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
Python (in browser)
n_neighbors sweep [5, 20, 50] — smaller k gives fine-grained local detection; larger k smooths out local variation and approaches global behaviour.
Python runs entirely in your browser via Pyodide (~6 MB on first Run, cached after).
LOF vs Isolation Forest decision guide — when local context matters and how to use LOF for online inference with novelty=True.
A point with LOF score 3 is...
- LOF compares a point's local reachability density to its neighbours' — LOF >> 1 means the point is much less dense than its neighbourhood → local outlier.
- LOF catches context-dependent anomalies that Isolation Forest misses — useful when clusters of very different densities coexist.
- n_neighbors controls the neighbourhood scale: small k = fine-grained local; large k = approaches global behaviour.
- For inference on new data, set novelty=True; without it LOF is transductive only.
- LOF is O(n²) — prefer Isolation Forest for large datasets (>100k rows) unless local context is critical.
Per-user fraud detection (each user has their own normal spending pattern), per-machine industrial monitoring (each machine has its own baseline vibration/temperature), clinical patient monitoring (anomalies relative to a patient's own history).
If you remove it: You'd miss context-dependent anomalies — a transaction that is normal for a high-spending customer but suspicious for a low-spending one would slip through a global detector.