Score events. Learn continuously. Adapt to the stream.
Documentation · Quickstart · Model guide · API reference · Changelog
aberrant is a typed Python library for unsupervised anomaly detection on data
that arrives one event at a time. Its models share a compact online interface:
score_one(x) evaluates the current event and learn_one(x) updates the model.
This lets an application adapt continuously without coordinating an external
batch-retraining loop.
Most models consume a dict[str, float], while graph and time-aware models
document their required keys explicitly. Detector state, warm-up behavior,
memory policy, and score scale remain model-specific rather than being hidden
behind a batch-estimator abstraction.
- Use one streaming contract across isolation forests, distance methods, sketches, graph detectors, online statistics, SVMs, time-series methods, and reconstruction models.
- Choose the right state strategy from sliding windows, bounded sketches, fading summaries, and model-specific incremental updates.
- Compose online preprocessing with detectors using
|pipelines. - Discover and configure built-ins through a typed catalog with machine-readable capabilities and an allowlisted declarative builder.
- Separate detection from policy with drift detectors and static or adaptive score thresholds.
- Run repeatable experiments with registry-backed benchmark streams and a validated local dataset cache.
- Compare streaming detectors with a catalog-aware
PrequentialEvaluator, explicit warm-up, bounded metric windows, and separate score/update timings. - Extend without framework coupling through typed, structural transformer
and model protocols. The distribution includes
py.typedmetadata.
aberrant requires Python 3.10 or newer and is continuously tested on CPython
3.10, 3.11, and 3.12.
pip install aberrantOptional extras
| Extra | Adds |
|---|---|
eval |
scikit-learn metrics for model evaluation |
dl |
the PyTorch-backed Autoencoder |
faiss |
the FAISS similarity-search engine used by models such as KNN |
benchmark |
River and pytest-benchmark |
docs |
the documentation build toolchain |
dev |
linting, typing, testing, and development dependencies |
all |
all optional and development dependencies |
For example:
pip install "aberrant[eval,faiss]"The following core-only example learns a scaled isolation forest from a synthetic stream. The first 64 events warm up the pipeline; every later event is scored before it is learned.
import numpy as np
from aberrant.model.iforest import OnlineIsolationForest
from aberrant.transform.preprocessing import StandardScaler
rng = np.random.default_rng(42)
stream = np.vstack(
[
rng.normal(size=(400, 2)),
rng.normal(loc=5.0, size=(20, 2)),
]
)
detector = StandardScaler() | OnlineIsolationForest(
num_trees=25,
window_size=256,
seed=42,
)
scores = []
for step, values in enumerate(stream):
event = {"x": float(values[0]), "y": float(values[1])}
if step >= 64:
scores.append((step, detector.score_one(event)))
detector.learn_one(event)
for step, score in sorted(scores, key=lambda item: item[1], reverse=True)[:5]:
print(f"event={step}, anomaly_score={score:.3f}")Higher scores are more anomalous under the common model contract, but their numeric range and calibration differ by detector. Compare or threshold scores only according to the selected model's documented semantics.
| Goal | Start with |
|---|---|
| General multivariate detection | OnlineIsolationForest or another isolation-forest variant |
| Local-neighborhood or density anomalies | LocalOutlierFactor, KNN, SDOStream, or a cell-based detector |
| Compact projection or frequency sketches | StreamingLODA, MStream, or StreamingRSHash |
| Anomalous edges and graph evolution | AnoEdgeL, ISCONNA, MIDAS, or SignedGraphSketchDetector |
| Discords in a scalar time series | RollingMatrixProfile or XLagDAMP |
| Departures from a known seasonal forecast | SeasonalResidualDetector |
| Changes in relationships between time-series channels | MultivariateRollingMatrixProfile |
| Interpretable rolling statistics | Univariate and multivariate moving statistics |
| Adaptive margin-based detection | Online SVM models |
| Learned reconstruction error | OnlineAutoencoderEnsemble or the optional PyTorch Autoencoder |
| Detecting distribution drift | ADWIN, KSWIN, or PageHinkley |
| Turning a score into an alert signal | QuantileThreshold or ThresholdModel |
See the model guide for inputs, score interpretation, warm-up behavior, and memory characteristics.
Included public model families
| Family | Implementations |
|---|---|
| Isolation forest | ASDIsolationForest, HalfSpaceTrees, MondrianIsolationForest, OnlineIsolationForest, RandomCutForest, StreamRandomHistogramForest, XStream |
| Distance | CellNeighborhoodDetector, KNN, LocalOutlierFactor, SDOStream, StationaryRegionNeighborDetector |
| Sketch | MStream, StreamingLODA, StreamingRSHash |
| Graph | AnoEdgeL, ISCONNA, MIDAS, SignedGraphSketchDetector |
| Time series | MultivariateRollingMatrixProfile, RollingMatrixProfile, SeasonalResidualDetector, XLagDAMP |
| SVM | GraphGatedOneClassSVM, IncrementalOneClassSVMAdaptiveKernel |
| Statistical | MovingAverage, MovingAverageAbsoluteDeviation, MovingGeometricAverage, MovingHarmonicAverage, MovingInterquartileRange, MovingKurtosis, MovingMedian, MovingQuantile, MovingSkewness, MovingVariance, MovingCorrelationCoefficient, MovingCovariance, MovingMahalanobisDistance |
| Reconstruction | OnlineAutoencoderEnsemble, optional Autoencoder |
| Score policy | QuantileThreshold, ThresholdModel |
| Baselines | NullModel, RandomModel |
| Drift detection | ADWIN, KSWIN, PageHinkley |
Transformers compose left to right, with at most one terminal model:
from aberrant.model.iforest import OnlineIsolationForest
from aberrant.transform import IncrementalPCA, StandardScaler
detector = (
StandardScaler()
| IncrementalPCA(n_components=3, n0=100)
| OnlineIsolationForest(window_size=512, seed=42)
)Any custom object satisfying TransformerProtocol or ModelProtocol can join
a pipeline; subclassing an aberrant base class is optional. Read the
pipeline guide
for lifecycle and composition rules.
RollingRobustScaler adds exact median/IQR scaling over bounded recent
feature windows. Its freeze() and unfreeze() controls make calibration
updates explicit; see the transformer guide
for readiness, zero-IQR behavior, and downstream coordinate considerations.
The built-in catalog makes model facts and construction available to services, configuration UIs, and deployment tooling without duplicating import paths or warm-up formulas:
from aberrant.catalog import DetectorConfig, get_model_spec
spec = get_model_spec("online_isolation_forest")
print(spec.parameter_schema())
config = DetectorConfig.from_mapping(
{
"transformers": [
{
"id": "feature_schema_guard",
"params": {"features": ["temperature", "pressure"]},
},
{"id": "standard_scaler"},
],
"model": {
"id": "online_isolation_forest",
"params": {"window_size": 512, "seed": 42},
},
}
)
detector = config.build()See the application integration guide for the catalog manifest, capability fields, KNN/FAISS configuration, and the boundary between package metadata and application policy.
The dataset API downloads, validates, and caches registered benchmark data, then exposes it as feature dictionaries and evaluation labels:
from itertools import islice
from aberrant.model.iforest import OnlineIsolationForest
from aberrant.stream.dataset import Dataset, load
dataset = load(Dataset.SHUTTLE)
detector = OnlineIsolationForest(num_trees=25, window_size=512, seed=42)
for event, label in islice(dataset.stream(), 100):
score = detector.score_one(event)
detector.learn_one(event)
print(f"label={label!r}, anomaly_score={score:.3f}")Labels are provided for evaluation; unsupervised detectors learn only from the event mapping. Cache location and download behavior are configurable through the streaming guide.