Skip to content

Distance and Neighborhood Models API

CellNeighborhoodDetector and StationaryRegionNeighborDetector are documented point-scoring adaptations, not exact reproductions of the source papers' set-level NETS and KDE/top-n STARE procedures.

KNN

Python
KNN(k: int, similarity_engine: BaseSimilaritySearchEngine)

Bases: BaseModel

Nearest-neighbor anomaly scorer backed by a search engine.

learn_one appends the observation to the supplied engine. score_one returns exactly the scalar produced by engine.search(x, n_neighbors=k); its range and orientation therefore belong to the engine's contract. With :class:~aberrant.similarity.FaissSimilaritySearchEngine, the score is the mean Euclidean distance to the k nearest retained observations, and higher values are more anomalous.

Parameters:

Name Type Description Default
k int

Number of neighbors requested for each score. Must be positive.

required
similarity_engine BaseSimilaritySearchEngine

Mutable search engine that owns the reference window.

required

Initialize a nearest-neighbor scorer.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Append one observation to the search engine.

Parameters:

Name Type Description Default
x dict[str, float]

Feature mapping to retain for subsequent queries.

required

score_one

Python
score_one(x: dict[str, float]) -> float

Query the engine for a k-neighbor scalar.

Parameters:

Name Type Description Default
x dict[str, float]

Feature mapping to query without appending it.

required

Returns:

Type Description
float

The value returned by the configured engine.

LocalOutlierFactor

Python
LocalOutlierFactor(k: int = 10, window_size: int = 1000, distance: Literal['euclidean', 'manhattan'] = 'euclidean')

Bases: BaseModel

Local Outlier Factor (LOF) for online anomaly detection.

LOF identifies anomalies by comparing the local density of a point with the local densities of its neighbors. Points with significantly lower density than their neighbors are considered outliers.

This implementation maintains a sliding window of observations and computes LOF scores on demand.

Note

Scoring recomputes the query neighborhood and the neighborhoods of its selected neighbors from the current window. Consequently, scoring cost grows quickly with k and window_size; bound both for latency-sensitive streams.

Parameters:

Name Type Description Default
k int

Number of neighbors to use for density estimation. Default is 10.

10
window_size int

Maximum number of points to keep in the window. Default is 1000.

1000
distance Literal['euclidean', 'manhattan']

Distance metric to use. Either "euclidean" or "manhattan". Default is "euclidean".

'euclidean'

Examples:

Python
from aberrant.model.distance import LocalOutlierFactor

stream = [
    {"x": 0.0, "y": 0.0},
    {"x": 0.1, "y": 0.0},
    {"x": 0.0, "y": 0.1},
    {"x": 3.0, "y": 3.0},
]
lof = LocalOutlierFactor(k=2, window_size=20)
scores = []
for point in stream:
    score = lof.score_one(point)
    scores.append(score)
    lof.learn_one(point)
assert len(scores) == len(stream)
References

Breunig, M. M., Kriegel, H. P., Ng, R. T., & Sander, J. (2000). LOF: identifying density-based local outliers. In Proceedings of the 2000 ACM SIGMOD International Conference on Management of Data (pp. 93-104). https://doi.org/10.1145/342009.335388

Pokrajac, D., Lazarevic, A., & Latecki, L. J. (2007). Incremental local outlier detection for data streams. In 2007 IEEE Symposium on Computational Intelligence and Data Mining (pp. 504-515).

n_points property

Python
n_points: int

Number of points currently in the window.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Add a new point to the window.

Parameters:

Name Type Description Default
x dict[str, float]

Feature dictionary with string keys and float values.

required

score_one

Python
score_one(x: dict[str, float]) -> float

Compute the LOF score for a point.

The LOF score indicates how anomalous a point is: - LOF ≈ 1: Point has similar density to its neighbors (normal) - LOF > 1: Point has lower density than neighbors (potential outlier) - LOF >> 1: Point is significantly less dense (strong outlier)

Parameters:

Name Type Description Default
x dict[str, float]

Feature dictionary with string keys and float values.

required

Returns:

Type Description
float

LOF score. Higher values indicate more anomalous points.

CellNeighborhoodDetector

Python
CellNeighborhoodDetector(k: int = 50, radius: float = 1.5, window_size: int = 10000, slide_size: int = 500, subspace_dim: int | None = None, time_key: str | None = None, warm_up_slides: int = 1, predict_threshold: float = 0.5, seed: int | None = None, eps: float = 1e-09)

Bases: BaseModel

Bounded cell-neighborhood streaming outlier detector.

The detector keeps a bounded sliding window and quantizes samples into full-space cells. Scores are based on neighborhood density within radius: score = 1 - min(neighbor_count / k, 1).

NETS-inspired cell indexing limits exact distance checks to neighboring cells. This class returns a continuous score for one query point; it does not reproduce the paper's exact window-level inlier/outlier set algorithm.

Notes: - Scores are continuous and bounded in [0, 1]. - State is bounded by window_size. - Feature schema is fixed after the first learn_one call. - Distance metric is Euclidean.

Parameters:

Name Type Description Default
k int

Neighbor count at which the scarcity score reaches zero.

50
radius float

Positive Euclidean neighborhood radius and grid-cell width.

1.5
window_size int

Maximum number of learned points retained. It must exceed k.

10000
slide_size int

Number of learned events per warm-up slide.

500
subspace_dim int | None

Compatibility parameter, validated against the feature count. The former subspace index was redundant and has been removed.

None
time_key str | None

Event-time field to exclude from the feature vector. None uses one-based arrival order; explicit times must be finite and non-decreasing.

None
warm_up_slides int

Complete slides required before non-zero scoring.

1
predict_threshold float

Score boundary used by predict_one.

0.5
seed int | None

Retained for constructor compatibility; scoring is deterministic.

None
eps float

Positive numerical floor used in bound calculations.

1e-09
References

Yoon, S., Lee, J.-G., & Lee, B. S. (2019). NETS: Extremely Fast Outlier Detection from a Data Stream via Set-Based Processing. https://doi.org/10.14778/3342263.3342269 Original implementation: https://github.com/kaist-dmlab/NETS

n_samples_seen property

Python
n_samples_seen: int

Number of samples processed via learn_one.

reset

Python
reset() -> None

Reset learned state while keeping hyperparameters.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Update the single bounded cell index with one sample.

score_one

Python
score_one(x: dict[str, float]) -> float

Count exact neighbors, stopping once the score must be zero.

predict_one

Python
predict_one(x: dict[str, float]) -> int

Return binary anomaly prediction using predict_threshold.

SDOStream

Python
SDOStream(k: int = 256, T: float = 512.0, qv: float = 0.3, x_neighbors: int = 6, distance: Literal['euclidean', 'manhattan', 'chebyshev', 'minkowski'] = 'euclidean', minkowski_p: float = 2.0, time_key: str | None = None, warm_up_observers: int | None = None, seed: int | None = None)

Bases: BaseModel

Streaming Density Observer detector.

SDOStream maintains a fixed-size set of observers and an exponentially decayed activity score per observer. A sample is scored by the median distance to its nearest active observers, where active observers are selected via activity quantile filtering.

Notes: - Scores are continuous, non-negative distances. - State is bounded by k and independent of stream length. - Feature schema is fixed after the first learn_one call.

Parameters:

Name Type Description Default
k int

Maximum number of observers retained.

256
T float

Positive fading time scale and observer-sampling time scale.

512.0
qv float

Activity quantile below which observers are excluded, in [0, 1).

0.3
x_neighbors int

Number of nearest active observers whose distances enter the median score. It cannot exceed k.

6
distance Literal['euclidean', 'manhattan', 'chebyshev', 'minkowski']

Distance metric: "euclidean", "manhattan", "chebyshev", or "minkowski".

'euclidean'
minkowski_p float

Positive order used only for Minkowski distance.

2.0
time_key str | None

Event-time field to exclude from the feature vector. None uses one-based arrival order; explicit times must be finite and non-decreasing.

None
warm_up_observers int | None

Observer count required before scoring. None resolves to at least x_neighbors and at least two, capped at k.

None
seed int | None

Seed for the model-local observer-sampling generator.

None
References

Hartl, A., Iglesias Vazquez, F., & Zseby, T. (2020). SDOstream: Low-Density Models for Streaming Outlier Detection. https://www.esann.org/sites/default/files/proceedings/2020/ES2020-143.pdf

n_observers property

Python
n_observers: int

Number of observers currently maintained by the model.

reset

Python
reset() -> None

Reset learned state while keeping hyperparameters.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Update model state with one sample.

Parameters:

Name Type Description Default
x dict[str, float]

Input feature dictionary.

required

score_one

Python
score_one(x: dict[str, float]) -> float

Compute anomaly score for one sample.

Parameters:

Name Type Description Default
x dict[str, float]

Input feature dictionary.

required

Returns:

Type Description
float

Continuous non-negative anomaly score.

StationaryRegionNeighborDetector

Python
StationaryRegionNeighborDetector(k: int = 50, radius: float = 1.0, window_size: int = 2048, slide_size: int = 128, skip_threshold: float = 0.1, time_key: str | None = None, warm_up_slides: int = 1, predict_threshold: float = 0.5, eps: float = 1e-09)

Bases: BaseModel

Stationary-region neighbor detector for streaming data.

The detector keeps a bounded sliding window and quantizes points into radius-sized grid cells. Scores are based on the number of neighbors within radius in the current window: score = 1 - min(neighbor_count / k, 1).

Candidate cell neighborhoods are reused while cell topology stays unchanged. Distances are always evaluated for the current query and live points. Unlike the paper, this class uses radius-neighbor counts rather than kernel-density estimates and returns a per-query score rather than a top-n outlier set.

Notes: - Scores are continuous and bounded in [0, 1]. - State is bounded by window_size. - Feature schema is fixed after the first learn_one call.

Parameters:

Name Type Description Default
k int

Neighbor count at which the scarcity score reaches zero.

50
radius float

Positive Euclidean neighborhood radius and grid-cell width.

1.0
window_size int

Maximum number of learned points retained. It must exceed k.

2048
slide_size int

Number of learned events per warm-up slide.

128
skip_threshold float

Compatibility parameter in [0, 1]. Approximate cached counts have been replaced by exact query-specific counts.

0.1
time_key str | None

Event-time field to exclude from the feature vector. None uses one-based arrival order; explicit times must be finite and non-decreasing.

None
warm_up_slides int

Complete slides required before non-zero scoring.

1
predict_threshold float

Score boundary used by predict_one.

0.5
eps float

Positive tolerance added to squared-distance comparisons.

1e-09
References

Yoon, S., Lee, J.-G., & Lee, B. S. (2020). Ultrafast Local Outlier Detection from a Data Stream with Stationary Region Skipping. https://doi.org/10.1145/3394486.3403171

n_samples_seen property

Python
n_samples_seen: int

Number of samples processed via learn_one.

reset

Python
reset() -> None

Reset learned state while keeping hyperparameters.

learn_one

Python
learn_one(x: dict[str, float]) -> None

Update detector state with one sample.

score_one

Python
score_one(x: dict[str, float]) -> float

Compute anomaly score for one sample.

predict_one

Python
predict_one(x: dict[str, float]) -> int

Return binary anomaly prediction using predict_threshold.

Optional FAISS engine

This engine requires aberrant[faiss].

FaissSimilaritySearchEngine

Python
FaissSimilaritySearchEngine(window_size: int, warm_up: int)

Bases: BaseSimilaritySearchEngine

Sliding-window exact Euclidean nearest-neighbor engine.

Observations are stored in a bounded FIFO window and indexed with FAISS IndexFlatL2. Although FAISS reports squared L2 distances, search converts them to Euclidean distances and returns their arithmetic mean. Feature names are sorted when the first observation is appended and must then remain identical. The engine returns 0.0 until warm_up observations have been retained.

Parameters:

Name Type Description Default
window_size int

Maximum number of data points to keep in the sliding window.

required
warm_up int

Minimum number of data points required before search can be performed.

required
Note

Requires the faiss optional dependency group: install aberrant[faiss].

append

Python
append(x: dict[str, float]) -> None

Add a data point to the search engine.

Parameters:

Name Type Description Default
x dict[str, float]

Dictionary representing a data point with feature names as keys.

required

search

Python
search(item: dict[str, float], n_neighbors: int) -> float

Search for the n nearest neighbors of a data point.

Parameters:

Name Type Description Default
item dict[str, float]

Dictionary representing the query data point.

required
n_neighbors int

Number of nearest neighbors to find.

required

Returns:

Type Description
float

Mean Euclidean distance to the requested nearest neighbors, or

float

0.0 before warm-up completes.

Raises:

Type Description
ValueError

If n_neighbors is not positive, exceeds the number of retained observations, or the feature schema differs.