Skip to content

Detectors

The lifecycle

Every detector follows the same three-method contract:

detector.fit(data, **params)      # trains, marks the detector fitted
detector.score(data)              # detector-specific anomaly scores
detector.detect_anomalies(data)   # fit-and-score convenience path

score() before fit() raises DetectorNotFittedError rather than returning nonsense. detect_anomalies() is what benchmark workflows call, and it returns scores that carry their orientation as metadata.

Score orientation

Detectors disagree about which direction means "more anomalous". Isolation Forest returns lower values for outliers; a distance-based detector returns higher ones. Comparing them naively inverts one of the two.

Every detector therefore declares a score_orientation:

Value Meaning
higher_is_more_anomalous larger score, more anomalous
lower_is_more_anomalous smaller score, more anomalous
binary_anomaly scores are 0 or 1
estimator_defined orientation unknown; rejected by benchmark evaluation

score() preserves each detector's native values, so nothing is silently rescaled. Benchmark evaluation calls canonicalize_anomaly_scores() to put everything on higher_is_more_anomalous before ranking.

This matters outside benchmarking too

analytics.hyperparam.grid_search once scored raw score() output. For a lower-is-more-anomalous detector that inverts the ROC AUC, so the search selected the worst parameters in the grid while reporting a plausible number. If you write your own evaluation loop, canonicalise first.

Available detectors

35 detectors ship in the registry. The key in the first column is what --detectors and get_detector_class() take.

Classical

Key Detector
isolation_forest Isolation Forest
knn k-Nearest Neighbors distance
hbos Histogram-Based Outlier Score
ocsvm One-Class SVM
elliptic_envelope Elliptic Envelope
gaussian_mixture Gaussian Mixture
sklearn_lof Local Outlier Factor (scikit-learn)
kmeans KMeans centroid distance
pca_reconstruction PCA reconstruction error
mahalanobis Mahalanobis distance
kde Kernel Density Estimation
sos Stochastic Outlier Selection
copod Copula-Based Outlier Detection
abod Angle-Based Outlier Detection
loda Lightweight On-line Detector of Anomalies
feature_bagging Feature Bagging ensemble
dbscan Inductive DBSCAN

dbscan lives in a correctness module rather than with the others: DBSCAN is transductive, so scoring unseen points needs an explicit inductive wrapper instead of the usual fit/predict pairing.

Modern tabular

Key Detector
ecod Empirical Cumulative Distribution Outlier Detection
random_feature_isolation_forest Random Feature Isolation Forest
random_network_distillation Random Network Distillation

Worth reaching for when distance, density, or covariance baselines are too rigid for nonlinear feature interactions. Classical methods remain preferable for small datasets, tight latency budgets, or when the score has to be explainable.

Deep — deep extra

Key Detector
autoencoder Autoencoder
denoising_autoencoder Denoising Autoencoder
variational_autoencoder Variational Autoencoder
anogan AnoGAN
madgan MAD-GAN

Temporal — deep extra

Key Detector
lstm_autoencoder LSTM Autoencoder
tcn_autoencoder Temporal Convolutional Network Autoencoder
transformer Transformer

Streaming — streaming extra

Key Detector
half_space_trees Half-Space Trees
online_isolation_forest Online Isolation Forest
random_cut_forest Random Cut Forest

random_cut_forest is not present in every River release; when the installed version does not provide it, selecting the key raises DependencyError naming the missing estimator rather than failing at import.

Graph

Key Detector
degree_centrality Degree Centrality
graph_isolation_forest Graph Isolation Forest

Forecasting

Key Detector
arima ARIMA residuals
prophet Prophet residuals (forecasting extra)

Every entry is registered as a dotted module:Class string and imported only when selected, so the heavy frameworks cost nothing until you ask for a detector that needs them.

Time-series semantics

Sequence detectors operate on genuine sequences rather than collapsing the time axis. A WindowSpec declares the windowing explicitly:

from anomalybench.analytics.time_series import WindowSpec

spec = WindowSpec(window_length=32, stride=1, horizon=0)

Window scores carry the point indices they align to, so a windowed score vector can be compared against point labels without the caller having to reconstruct the alignment. Mismatches raise rather than silently comparing unaligned vectors.