Unsupervised learning
Local Outlier Factor and Neighborhood Anomalies
Understand reachability distance, local density ratios, neighborhood size, and the difference between global and local anomalies.
By the end you can
- Explain local reachability density and the intuition behind Local Outlier Factor
- Distinguish local outliers from globally extreme observations
- Choose neighborhood size with density scale and sample support in mind
- Recognize high-dimensional, duplicate, boundary, and novelty-mode limitations
Visual
The LOF reasoning chain
Local Outlier Factor compares the effective density around a point with the densities around its neighbors, in five steps. Select a k-neighborhood under the chosen feature geometry. Limit very small pairwise distances using each neighbor's k-distance, giving reachability distances. Invert the average reachability distance from the point to its neighbors to estimate a local density. Average the ratio of neighbor density to the point's own density. Rank observations by that ratio.
The last step rests on a proof, not a convention. Take an object p whose MinPts-nearest neighbours, and their MinPts-nearest neighbours, all lie inside a cluster C. Its score is then trapped between two computable bounds: 1/(1+ε) ≤ LOF(p) ≤ (1+ε), with ε = (reach-dist-max/reach-dist-min − 1). That is Lemma 1 of the paper that introduced the score, published in 2000. Breunig and his three co-authors state the consequence plainly: “Lemma 1 above shows a basic property of LOF, namely that for objects deep inside a cluster, their LOFs are close to 1, and should not be labeled as a local outlier.”
That bound is why scikit-learn can tell a user, in the docstring of its LocalOutlierFactor class, that “Inliers tend to have a LOF score close to 1”. A value near one is not a soft verdict of innocence. It is the arithmetic of a density ratio whose numerator and denominator are drawn from the same region. The width of the band around one is ε, a property of the data rather than of the analyst.
1. Select neighbors
Find a k-neighborhood under the chosen feature geometry.
2. Compute reachability
Limit very small pairwise distances using each neighbor’s k-distance.
3. Estimate local density
Invert the average reachability distance from the point to its neighbors.
4. Compare densities
Average the ratio of neighbor density to the point’s density.
5. Rank observations
Values near one look locally typical; larger factors indicate local sparsity.
Deep inside a cluster the score is pinned between 1/(1+ε) and 1+ε: LOF is a relative local-density ratio, not a probability of wrongdoing.
A defender with six goals outranked almost every striker in the league
Six goals in 15 games is a forgettable season. That was Michael Schjönberg's in the German Bundesliga in 1998/99, and measured against the league it is nothing: the season's top scorer, Michael Preetz, finished on 23 goals, ahead of Ulf Kirsten on 19. Yet when the four authors of the LOF paper ran their new score over the 375 players of that season, sweeping MinPts from 30 to 50, Schjönberg came out as the second strongest outlier in the data, at LOF 1.70. The paper says why in one sentence: “The second strongest outlier is Michael Schjönberg. He played an average number of games, but he was an outlier because most other defense players had a much lower average number of goals scored per game.”
Above him at LOF 1.87 sat Preetz: 34 games, 23 goals, offence, extreme on any scale you care to apply. Below him at LOF 1.67 sat the goalkeeper Hans-Jörg Butt, 34 games and 7 goals. That is an enormous number for a goalkeeper and a modest one for anybody else. A global threshold on goals scored returns Preetz and stops. The local density ratio returns all three. Two of the three exist only because each player was scored against the density of players in his own position.
Local outlier methods compare each point with the density of nearby points. Their strength is exactly this context. Their weakness is that the context is a modelling choice. The peer group has to be trustworthy before the ranking means anything.
Schjönberg's six goals are ordinary in the league and extraordinary among defenders; only a local reference can tell those two facts apart.
Example
LOF failure signatures
Local methods need example-level review across density and boundary conditions. Three of the five signatures below are documented in the method's own founding paper or in the published benchmarks, with the numbers attached.
- Boundary inflation: points between two valid clusters have lower local density than either cluster and receive high scores despite representing a normal transition. A high score in a transition region is a statement about geometry, not about conduct.
- Duplicate suppression: the failure is written into the definition itself. The remark following Definition 6, local reachability density, says so outright: “Note that the local density can be ∞ if all the reachability distances in the summation are 0. This may occur for an object p if there are at least MinPts objects, different from p, but sharing the same spatial coordinates, i.e. if there are at least MinPts duplicates of p in the dataset.” LOF divides neighbor densities by the point's own. So an infinite density inside a pile of repeated records makes legitimate points nearby look anomalous by comparison. scikit-learn watches for precisely this: in the default outlier-detection mode, LocalOutlierFactor.fit raises the runtime warning “Duplicate values are leading to incorrect results. Increase the number of neighbors for more accurate results.” when the smallest fitted negative outlier factor drops below -1e7.
- Small group ambiguity: the original paper's own synthetic experiment puts a range on it. Three clusters — S1 with 10 objects, S2 with 35 and S3 with 500 — and the members of the 10-object cluster S1 register as strong outliers only while MinPts lies between 10 and 35. Below 10, statistical fluctuation dominates the density estimate. Above 35, S1's members begin borrowing the next cluster along as their reference, and a rare coherent population stops being scored as one.
- Hub distortion: the collapse has been measured. On the speech dataset — 400 dimensions, 3,686 instances, 1.65% anomalies — LOF returned an AUC of 0.5038 ± 0.0215 averaged over 10 ≤ k ≤ 50. That is chance. Only k < 5 gave usable results. Goldstein and Uchida ran that test; the mechanism came from a 2010 paper in the Journal of Machine Learning Research, where k-occurrence skew produces antihubs: “Based on the observations regarding hubness and the behavior of distances discussed earlier, we believe that the true problem actually lies in the opposite extreme: high dimensionality induces antihubs that can represent “artificial” outliers.” Radovanović, Nanopoulos and Ivanović wrote that. Flexer and Schnitzer reported the same negative impact of hubness on outlier detection independently in 2013.
- Context leakage: a feature recorded after an incident creates unnaturally sharp local separation, and the neighborhood graph obligingly reproduces it. The score will look excellent in evaluation and will not survive contact with a reference period that ends before the outcome does.
Key idea
Training mode and novelty mode are not interchangeable
Some implementations use LOF primarily to identify outliers within the fitted sample. Novelty detection for unseen data follows a different interface and should not score the training data in the same way. Document which setting the system uses. Test held-out assignment explicitly. An API flag can change the operational meaning of the score.
scikit-learn draws that line inside one class, and says so in its own documentation: “By default, LocalOutlierFactor is only meant to be used for outlier detection (novelty=False). Set novelty to True if you want to use LocalOutlierFactor for novelty detection”. Flipping it changes what you are allowed to score. In that mode “you should only use predict, decision_function and score_samples on new unseen data and not on the training set”. One boolean argument decides which population the score describes. The identical passage sits in the implementation, sklearn/neighbors/_lof.py, not only in the rendered docs.
The neighborhood is a default too, and a quieter one. The API reference lists “n_neighbors int, default=20”. Nothing in your data chose that number for you.
Know whether the model is diagnosing its reference sample or scoring future observations, and record which boolean says so.
Steps
Qualify a local-density anomaly detector
The neighborhood scale should be selected through operational and geometric evidence, not inherited from a library default.
1. Validate feature geometry. Review scaling, high-dimensional behavior and nearest-neighbor examples. The peers a point is scored against are produced by the metric. Change the scaling and the point gets a different set of neighbors to be unusual against.
2. Sweep k. There is a published range to sweep around rather than a single correct value. The original paper recommends a MinPtsLB of at least 10 to remove statistical fluctuations, and for the general case writes: “For most of the datasets we experimented with, picking 10 to 20 appears to work well in general.” scikit-learn hard-codes the top of that range as n_neighbors=20 and repeats the reasoning in its user guide: “In practice, such information is generally not available, and taking n_neighbors=20 appears to work well in general.” Compare score rankings across neighborhoods smaller and larger than the local groups you expect, and record how the ranking moves.
3. Inspect regimes. Review dense, sparse, boundary, rare-group and duplicated regions separately. Each of the failure signatures above lives in a different region, and an aggregate metric averages them away.
4. Compare baselines. Test global distance, peer-group rules and isolation methods on the same alert budget, and expect no outright winner. ADBench, a 2022 benchmark, ran 30 algorithms across 57 datasets in 98,436 experiments. Its critical-difference analysis reported that “None of the unsupervised methods is statistically better than the others”. Selection therefore has to be made on the anomaly type you actually face, not on a leaderboard.
5. Validate future scoring. Use later observations and delayed adjudication when novelty detection is intended, with the novelty flag set deliberately and the reference period written down.
1. Validate feature geometry
Review scaling, high-dimensional behavior, and nearest-neighbor examples.
2. Sweep k
Compare score rankings across neighborhoods smaller and larger than expected local groups.
3. Inspect regimes
Review dense, sparse, boundary, rare-group, and duplicated regions separately.
4. Compare baselines
Test global distance, peer-group rules, and isolation methods on the same alert budget.
5. Validate future scoring
Use later observations and delayed adjudication when novelty detection is intended.
Analogy
Finding an empty house on a crowded street
How unusual a house is depends on the street it stands in, not on the country. A modest property can stand out if every neighboring building is densely occupied. This is the same move that put a defender with 6 goals above almost every striker in the Bundesliga. The comparison set produced the ranking, not the raw quantity.
Geographic neighbors are visible. Feature-space peers depend on scaling, metric and available variables. Change the scaling and a point acquires a different set of peers to be unusual against. In 400 dimensions the street itself dissolves. That is what an AUC of 0.5038 on the speech dataset is describing.
Local anomaly quality depends on the credibility of local peers, and in high dimension those peers stop being local at all.
Comparison
Global and local anomaly views
A heterogeneous dataset can contain several normal density regimes. The choice between a global and a local reference is measurable on the same data, not a matter of taste.
The measurement is blunt. On pen-local, LOF reaches an AUC of 0.9877 ± 0.0016. On pen-global — the same pen-based data preprocessed to carry global anomalies instead of local ones — it falls to 0.8495 ± 0.0679. On kdd99 it reaches 0.5964 ± 0.0284, a dataset where a global k-NN score reaches 0.9747. Goldstein and Uchida published all three in 2016. The algorithm did not change between those numbers. Only the kind of anomaly did.
A global distance score measures distance from a center or broad reference. It finds globally extreme points, can miss anomalies inside subpopulations, is simple to explain, and assumes one broad normal scale. Local Outlier Factor compares density with nearby points. It adapts to local regimes, depends on neighborhood quality, can flag boundary points, and needs k sensitivity checks. A peer-group baseline defines neighborhoods through known entity or context groups — defenders scored against defenders rather than against the league. It uses domain structure, can reduce confounding, requires reliable peer assignment, and may miss cross-group novelty.
ADBench reached the same conclusion across 57 datasets: “Again, there is no algorithm performing well on all types of anomalies; LOF achieves the best AUCROC on local anomalies (Fig. 5a) and the second best AUCROC rank on dependency anomalies (Fig. 5c), but performs poorly on clustered anomalies (Fig. 5d).” Two independent benchmarks, six years apart, put the decision in the same place. Name the anomaly type first, then pick the detector.
Global distance score
Measures distance from a center or broad reference.
- Finds globally extreme points
- Can miss anomalies inside subpopulations
- Is simple to explain
- Assumes one broad normal scale
Local Outlier Factor
Compares density with nearby points.
- Adapts to local regimes
- Depends on neighborhood quality
- Can flag boundary points
- Needs k sensitivity checks
Peer-group baseline
Defines neighborhoods through known entity or context groups.
- Uses domain structure
- Can reduce confounding
- Requires reliable peer assignment
- May miss cross-group novelty
Local methods trade global simplicity for neighborhood dependence
LOF can identify subtle anomalies in populations with several normal density regimes. It does so by trusting the local graph around each point. When those neighborhoods are unstable, contaminated or semantically wrong — duplicated records, a cluster smaller than MinPts, 400 dimensions — the score inherits the problem, and it inherits it silently. Report neighborhood sensitivity with every operational threshold, alongside the k you swept and the reference period you used.
The comparison behind the word “local” was run in PLOS ONE in 2016, over “19 different unsupervised anomaly detection algorithms … on 10 different datasets from multiple application domains”. Goldstein and Uchida's working definition is the useful part. A point is a local anomaly when it is “only anomalous when compared with its close-by neighborhood”. Whether that kind of anomaly matters, they add, “depends on the application”.
That last clause is the whole operational question. Schjönberg is anomalous only among defenders. Preetz, at LOF 1.87 and 23 league goals, is anomalous in either frame. A system that can only see the second is cheaper to explain and blind to half the problem. A system that sees the first has taken on the obligation to justify its neighborhoods.
The local reference is both LOF's advantage and its primary risk, and it is the part of the system nobody audits.
Key takeaways
- LOF scores unusualness relative to local neighborhood density. Lemma 1 of the original 2000 paper pins objects deep inside a cluster between 1/(1+ε) and 1+ε, which is why scikit-learn documents that inliers score close to 1.
- Local comparison can reveal anomalies inside heterogeneous normal populations: Michael Schjönberg, 15 games and 6 goals, ranked second among the 375 Bundesliga players of 1998/99 at LOF 1.70 because he was scored against defenders rather than against the league.
- Neighborhood size determines which density scale the method sees. The original paper recommends 10 to 20 with a MinPtsLB of at least 10, scikit-learn defaults to n_neighbors=20, and in the S1/S2/S3 experiment the 10-object cluster is a strong outlier only for MinPts between 10 and 35.
- Boundaries, duplicates, small groups and high-dimensional hubs distort scores: local reachability density becomes infinite at MinPts duplicates, and on the 400-dimensional speech dataset LOF fell to an AUC of 0.5038 ± 0.0215.
- Outlier detection on the reference sample differs from novelty scoring on new data, and in scikit-learn a single boolean, novelty, decides which of the two the score means.
- LOF should be compared with global, peer-group and isolation baselines: 0.9877 on pen-local against 0.5964 on kdd99, where global k-NN reaches 0.9747, and ADBench found no unsupervised method statistically better than the others across 57 datasets.