Skip to main content

English · 简体中文

PySAD

One pass. Every outlier.

Streaming anomaly detection in Python. PySAD scores each data point when it arrives,
with streaming detectors, calibrated alerts and streaming evaluation.

PyPI version conda-forge version Python versions License DOI
Tests pre-commit.ci status Coverage Documentation Last commit

Documentation · Getting started · How-to guides · Benchmarks · Detectors · API · Live demo · Try it in Colab

Three sensor readings stream in from left to right. A Robust Random Cut Forest scores each point when the point arrives. Conformal calibration raises alerts at a spike, a short plateau and a dip.

A Robust Random Cut Forest scores three synthetic sensors one point at a time. Conformal calibration converts each score into the fraction of recent scores that it exceeds, and raises an alert at 0.995.

Why PySAD

A batch detector needs the whole dataset before it can score a point. A stream does not give you the whole dataset. Points arrive one at a time, the data drifts (its distribution changes over time), and you must decide about each point before the next point arrives. PySAD is built for this setting. More than 60 publications on Google Scholar cite it, and 30+ public repositories on GitHub use it.

Built for streams

Every detector learns from and scores one point at a time with fit_partial, score_partial and fit_score_partial. Most detectors keep a window, a sketch or a set of trees of fixed size instead of the whole stream.

Detectors from published papers

From robust statistics (MAD, Seasonal Hybrid ESD) to forests, sketches and projections (Half-Space Trees, Robust Random Cut Forest, RS-Hash, xStream, LODA). Each detector cites its paper, and the detector catalog lists its input and memory.

From scores to alerts

The conformal calibrator converts a raw score into the fraction of recent scores that it exceeds. A threshold such as 0.99 then has the same meaning for every detector.

Evaluate on the stream

Streamers replay data one point at a time, and 17 labeled benchmark datasets download on first use. Metrics such as AUROC, AUPR, precision and recall update after every point.

Your batch models on a stream

Wrap any PyOD detector to train it again on a sliding window of recent points.

A complete pipeline

Preprocessors, random projections, score postprocessors, ensemblers and running statistics work with every detector.

Batch outlier detectors such as PyOD train on a fixed dataset and must train again to use new data. PySAD detectors learn from every point, and PySAD can still run PyOD models on a stream with ReferenceWindowModel. General online learning frameworks such as River treat anomaly detection as one module among many. PySAD is only about streaming anomaly detection: its detectors come with calibration, postprocessing, ensembling and evaluation.

Installation

pip install pysad

Or with Conda / Mamba / Pixi:

conda install -c conda-forge pysad

PySAD supports Python 3.10 to 3.14 on Linux, macOS and Windows. Every detector works after installation, with no optional extras.

To install the latest development version from master:

pip install git+https://github.com/selimfirat/pysad.git

For an editable installation with development dependencies, follow the contributing guide.

Quick start

Open in JupyterLite Open in Colab

Score a stream point by point, and measure the detector while it runs:

import numpy as np
from pysad.evaluation import AUROCMetric
from pysad.models import LODA
from pysad.utils import ArrayStreamer

# A stream of 2,000 points with 4 features. Every 50th point is an anomaly.
rng = np.random.default_rng(42)
X = rng.normal(size=(2000, 4))
y = np.zeros(2000, dtype=int)
y[::50] = 1
X[y == 1, :2] += 3  # the code shifts the anomalies in two of the four features

model = LODA(random_state=0)
metric = AUROCMetric()

for x, label in ArrayStreamer().iter(X, y):
    score = model.fit_score_partial(x)  # score x, then learn from it
    metric.update(label, score)

print(f"AUROC: {metric.get():.3f}")  # prints AUROC: 0.960

Turn scores into alerts

A higher score means a more anomalous point, but raw scores have no fixed scale. The conformal calibrator converts each score into the fraction of recent scores that it exceeds. Continuing the example above, raise an alert when this value is close to 1:

from pysad.transform.probability_calibration import ConformalProbabilityCalibrator

model = LODA(random_state=0)
calibrator = ConformalProbabilityCalibrator(window_size=500)

alerts = []
for t, x in enumerate(ArrayStreamer().iter(X)):
    calibrated = calibrator.fit_transform_partial(model.fit_score_partial(x))
    if t >= 200 and calibrated >= 0.99:  # skip a short warm-up
        alerts.append(t)

# Prints: 20 alerts, 15 of them true anomalies
print(f"{len(alerts)} alerts, {y[alerts].sum()} of them true anomalies")

Stream your own data

A detector takes one NumPy array per point, so any loop works: a CSV reader, a socket or a message queue consumer.

import json

for message in consumer:  # for example, a Kafka consumer
    x = np.asarray(json.loads(message.value)["features"], dtype=float)
    score = model.fit_score_partial(x)

ArrayStreamer, PandasStreamer and PolarsStreamer replay arrays and pandas or Polars DataFrames as streams for experiments.

Use a PyOD model on a stream

Install PyOD first with pip install pyod.

from pyod.models.iforest import IForest
from pysad.models.integrations import ReferenceWindowModel

# Train a batch Isolation Forest on the last 200 points, again every 50 points.
model = ReferenceWindowModel(IForest, window_size=200, sliding_size=50, initial_window_X=X[:100])
for x in ArrayStreamer().iter(X[100:]):
    score = model.fit_score_partial(x)

The getting started tutorial explains each step. The how-to guides cover alerts, evaluation, pipelines, seasonal series, production use and custom detectors.

Detectors

Which detector to start with

Your data Start with Why
One series of values with daily or weekly cycles SeasonalHybridESD Removes the cycle. Earlier anomalies in the window have little effect on it
One series of values without a strong cycle MedianAbsoluteDeviation Anomalies in the window have little effect on it. It uses only recent values, so it follows drift
Several features, first try LODA Fast, has few parameters and learns from every point
Features with known value ranges HalfSpaceTrees Constant time per point, scored against the previous window
Many features xStream Projects the points to fewer features with hashing
Network traffic KitNet Built for network intrusion detection. Gives 0 for the first 100 points by default
A PyOD model that you already use ReferenceWindowModel Trains it again on a sliding window

These starting points come from the design of each method. They are not benchmark rankings. The benchmark gives the results of each multivariate detector on 17 datasets. Compare two or three detectors on your own data, as the guide to choosing a detector shows.

All detectors

Multivariate

Class Method
xStream xStream (Manzoor et al., KDD 2018)
LODA Lightweight on-line detector of anomalies (Pevný, Machine Learning 2016)
HalfSpaceTrees Half-Space Trees (Tan et al., IJCAI 2011)
RobustRandomCutForest Robust Random Cut Forest (Guha et al., ICML 2016)
RSForest RS-Forest random space tree density (Wu et al., ICDM 2014)
RSHash RS-Hash subspace outlier detection (Sathe & Aggarwal, ICDM 2016)
MStream MStream multi-aspect stream counts (Bhatia et al., WWW 2021)
MIDAS MIDAS edge counts of a graph stream (Bhatia et al., AAAI 2020)
IForestASD Isolation Forest on sliding windows (Ding & Fei, IFAC 2013)
OnlineIsolationForest Online Isolation Forest (Leveni et al., ICML 2024)
KitNet KitNET ensemble of autoencoders (Mirsky et al., NDSS 2018)
ExactStorm Exact-STORM distance-based outliers (Angiulli & Fassetti, CIKM 2007)
ApproxStorm Approx-STORM distance-based outliers from a sample of the window (Angiulli & Fassetti, CIKM 2007)
MCOD Micro-cluster-based distance-based outliers (Kontaki et al., ICDE 2011)
NETS Set-based distance-based outliers on a cell grid (Yoon et al., PVLDB 2019)
CPOD Core point-based distance-based outliers (Tran et al., PVLDB 2020)
D3 Distance-based outliers from a kernel density over a chain sample of a window (Subramaniam et al., VLDB 2006)
ThreshLEAP Distance-based outliers with minimal, newest-first probing (Cao et al., ICDE 2014)
IncrementalLOF Incremental local outlier factor (Pokrajac et al., CIDM 2007)
OnlineOneClassSVM Online one-class SVM, NORMA (Kivinen et al., IEEE TSP 2004)
DILOF Density summarizing incremental LOF (Na et al., KDD 2018)
KELOS Kernel density local outliers over micro-clusters of a window (Qin et al., EDBT 2019)
AnyOut Anytime outliers by distance to the closest cluster of a ClusTree (Assent et al., DASFAA 2012)
ADeMS Frequent Directions matrix sketch (Huang & Kasiviswanathan, VLDB 2015)
LocalOutlierProbability Local Outlier Probabilities (Kriegel et al., CIKM 2009)
Inqmad InQMAD quantum measurement density (Gallego-Mejia et al., ICDMW 2022)
SmartSifter Finite mixtures with discounting learning (Yamanishi et al., KDD 2000)
TEDA Typicality and eccentricity data analytics (Angelov, EALS 2014)
EXPoSE Expected similarity to the kernel mean embedding (Schneider et al., Machine Learning 2016)

Univariate

Class Method
SeasonalHybridESD Seasonal Hybrid ESD (Hochenbaum et al., 2017)
SeasonalESD Seasonal ESD (Hochenbaum et al., 2017)
HTM Hierarchical Temporal Memory, the numenta detector of NAB, on timestamped values (Ahmad et al., Neurocomputing 2017)
KNNCAD Conformalized k-NN anomaly detection (Burnaev & Ishimtsev, 2016)
HoltWinters Holt-Winters forecasting with a seasonal confidence band and a failure window (Brutlag, USENIX LISA 2000)
ChangeFinder Outlier and change point detection with discounting AR models (Takeuchi & Yamanishi, TKDE 2006)
MatrixProfile Matrix profile discords with STAMPI (Yeh et al., ICDM 2016)
DAMP Left matrix profile discords with a backward search that stops early (Lu et al., KDD 2022)
SpectralResidual Spectral residual saliency over a sliding window (Ren et al., KDD 2019)
RelativeEntropy Relative entropy over windows (Wang et al., IM 2011)
SAND Streaming subsequence anomaly detection with k-Shape clusters (Boniol et al., PVLDB 2021)
MedianAbsoluteDeviation Median absolute deviation over a sliding window (Hochenbaum et al., 2017)
StandardAbsoluteDeviation Running 3-sigma rule (Hochenbaum et al., 2017)

ReferenceWindowModel and OneFitModel run any PyOD detector on a stream. The detector catalog lists the input, setup and memory of each detector, and the API reference lists every parameter.

Benchmarks

PySAD benchmarks its detectors on labeled data. The 10 multivariate detectors run on 17 datasets from the ODDS repository and on 8 real streams with drift. The univariate detectors run on the series of the Numenta Anomaly Benchmark (NAB) and of the UCR archive. Each detector runs once on each dataset, with its default parameters, and scores each point before it learns from it (fit_score_partial).

The benchmark results page shows all the results. The evaluation methodology explains the steps, the metrics and the limits of the results, and the datasets page describes the data. To run the benchmark, use python benchmarks/benchmark.py, as Run the benchmark shows. On each pull request that changes a detector, CI runs a short form of the benchmark and lists the results that moved.

Beyond detectors

Stage What PySAD provides
Preprocessing InstanceStandardScaler, InstanceUnitNormScaler, SeasonalTrendDecomposer, ModifiedSTLResidualTransformer, OneShotSTL
Projection StreamhashProjector, GaussianRandomProjector, SparseRandomProjector
Postprocessing Running and windowed average, max, median and z-score of scores, and QuantileFilter for 0/1 labels
Calibration AnomalyLikelihoodProbabilityCalibrator, ConformalProbabilityCalibrator, GaussianTailProbabilityCalibrator, SPOTProbabilityCalibrator
Ensembling Average, maximum, median, average-of-maximum and maximum-of-average score ensemblers
Evaluation AUROCMetric, AUPRMetric, PrecisionMetric, RecallMetric, WindowedMetric
Streaming data ArrayStreamer, PandasStreamer, PolarsStreamer, and Data for 17 labeled ODDS benchmark datasets, downloaded on first use
Statistics Running mean, variance, median, min, max, sum and count

Contributing

We welcome issues and pull requests, and we aim to reply within a few days. Ask questions and share your projects in Discussions. For a first contribution, choose a good first issue. The contributing guide lists the steps from the first clone to an open pull request.

PySAD follows semantic versioning and trunk-based development. Each change reaches master through a short-lived branch and a pull request that CI checks, and CI runs every example.

Contributors

Thanks to everyone who has reported a bug, fixed one, or improved the docs.

Citing PySAD

If you use PySAD in a scientific publication, cite the paper:

@article{pysad,
  title={PySAD: A Streaming Anomaly Detection Framework in Python},
  author={Yilmaz, Selim F and Kozat, Suleyman S},
  journal={arXiv preprint arXiv:2009.02572},
  year={2020}
}

To cite a specific version of the software, use its Zenodo DOI. The DOI 10.5281/zenodo.22983312 always points to the latest release. That page also lists a separate DOI for each release.

License

PySAD is free software under the BSD 3-Clause License.


Tripod, the PySAD mascot: a tripodfish that stands still on three long fins and waits for what the current brings.

If PySAD is useful to you, a star helps other people find it.
To hear about new detectors and releases, choose Watch → Custom → Releases.

Metadata

Release files for pysad 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pysad 0.8.0
File Size Uploaded Provenance Actions
pysad-0.8.0.tar.gz 232.5 kB With provenance Details for pysad-0.8.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for pysad 0.8.0
File Interpreter ABI Platform Actions
pysad-0.8.0-py3-none-any.whl Python 3 none any Details for pysad-0.8.0-py3-none-any.whl

Total release size: 524.7 kB

Release files / pysad-0.8.0.tar.gz

Download URL pysad-0.8.0.tar.gz
Size 232.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7df09667f0d6742ebc444dee074edeba48bccc5ad2ce2b2ba5520dd131ed88aa
BLAKE2b-256 checksum
How to use checksums
f9a91b093fa913af481747627f3732649c6337c22f0a3a2ceec5346c98fc43f6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Release files / pysad-0.8.0-py3-none-any.whl

Download URL pysad-0.8.0-py3-none-any.whl
Size 292.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
2e0b254e7ab3b545fb1011e37317105148f532ccbed8a7464cc62ed9debce341
BLAKE2b-256 checksum
How to use checksums
4f340ad7afa106bfca1e9152c2e6735722af2a648d7dfdba75c3b79a38ddcc4f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.16

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

Security for pysad 0.8.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

Both files in this release have been uploaded with provenance metadata.

Select from 2 files

Attestation for pysad-0.8.0.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Nov 8, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page