ABOD - Angle-Based Outlier Detection.
Classes
ABOD detects outliers from the variance of angles to other points.
__init__( self, n_neighbors: int = 10, contamination: float = 0.1, )
Overview
-
For a point x, take its
n_neighborsnearest neighbours. - For every pair of those neighbours, compute the angle they subtend at
- The score is the variance of those weighted cosines.
- Small variance means the surrounding points are all in one direction,
Theory
The angle-based outlier factor of x is the variance
over pairs y, z drawn from the point's neighbourhood. The \|\cdot\|^2 weighting in the denominator makes distant pairs count less, so the measure blends angular spread with proximity rather than being purely angular.
Exact ABOD considers all pairs, at O(n^3) — unusable beyond a few hundred points. This class implements FastABOD, which restricts the pairs to each point's n_neighbors nearest neighbours, giving O(n^2 d + n k^2). The approximation is good precisely when it matters: the neighbours dominate the weighted variance anyway.
Parameters
n_neighbors
contamination
Attributes
X_train_
threshold_
n_features_in_
fit.
Notes
Complexity. Scoring is O(m n d) for the neighbour search plus O(m k^2 d) for the pairwise angles. Memory is O(n d). The distance matrix is computed by the shared C++ kernel tuiml._cpp_ext.distance.
When to use. ABOD earns its cost in high dimension, where KNNDetector and LocalOutlierFactorDetector degrade as distances concentrate. In low dimension it offers little over kNN for considerably more compute. As with any geometric method, scale the features first.
Warning — clustered anomalies mask each other. ABOD assumes anomalies are isolated. When several sit together in a tight group, each one's nearest neighbours are the other anomalies, which surround it from all sides; worse, the 1/\|\cdot\|^2 weighting rewards a tight neighbourhood with a large factor. The group then scores as more normal than the genuine inliers and the ranking inverts. Measured on 300 Gaussian inliers in 50 dimensions with 15 anomalies placed at distance 6:
====================== ========== ========== anomaly cluster spread ABOD AUC kNN AUC ====================== ========== ========== 0.05 (very tight) 0.00 1.00 0.30 0.00 1.00 1.00 (as spread as 0.04 1.00 the inliers) 2.00 1.00 1.00 ====================== ========== ==========
The same effect shows up as the anomaly count grows: 1 or 3 isolated anomalies score 1.00, while 15 clustered ones score 0.19. If anomalies may arrive in bursts — a batch of fraudulent transactions, a stuck sensor emitting the same reading — use KNNDetector or ECODDetector instead, neither of which has this failure mode.
References
See Also
>>> import numpy as np
>>> from tuiml.algorithms.anomaly import ABODDetector
>>> rng = np.random.default_rng(0)
>>> X = np.vstack([rng.normal(0, 1, (200, 20)), rng.normal(6, 1, (3, 20))])
>>> detector = ABODDetector(n_neighbors=10, contamination=0.05).fit(X)
>>> int((detector.predict(X)[-3:] == -1).sum()) # isolated anomalies
3
Replacing those 3 isolated anomalies with a tight group of 15 inverts the
ranking entirely — see the warning above before choosing this detector.
Methods
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'ABODDetector'
fit
(self, X: np.ndarray, _y: Optional[np.ndarray]=None) -> 'ABODDetector'
Fit the ABOD detector.
Parameters
X
_y
Returns
self