pattern-drift
Automatic concept drift detection for streaming datasets.
pattern-drift is a Python library for data scientists and ML engineers working with time-sensitive models. It continuously monitors incoming data distributions, detects statistical drift, and recommends optimal retraining windows — keeping models accurate without manual monitoring.
Installation
pip install pattern-drift
Optional extras:
pip install pattern-drift[viz] # adds matplotlib for drift timeline visualisation
pip install pattern-drift[alerts] # adds requests for Slack and webhook callbacks
pip install pattern-drift[all] # everything
Quick Start
from pattern_drift import DriftMonitor
monitor = DriftMonitor(method="ADWIN", sensitivity=0.002)
for record in stream: # dict, pandas Series, or single-row DataFrame
result = monitor.update(record)
if result.drift_detected:
print(f"Drift! type={result.drift_type}")
print(f"Features: {result.drifted_features}")
print(f"Score: {result.drift_score:.4f}")
if result.retraining_window:
rw = result.retraining_window
print(f"Retrain on records {rw.start}–{rw.end} (confidence {rw.confidence:.2%})")
Detection Algorithms
| Algorithm | Mechanism | Best For |
|---|---|---|
ADWIN (default) |
Variable-length window split testing on mean differences | Gradual drift — adapts window size dynamically |
PageHinkley |
Cumulative sum of deviations from the running mean | Sudden drift — extremely fast and memory-efficient |
KSWIN |
Kolmogorov-Smirnov test comparing recent vs. reference window | Distribution shape changes beyond just mean shifts |
DDM |
Monitors prediction error rate vs. historical minimum | Classifier performance monitoring post-deployment |
Switch algorithms with a single parameter — no other code changes required:
monitor = DriftMonitor(method="PageHinkley")
monitor = DriftMonitor(method="KSWIN")
monitor = DriftMonitor(method="DDM")
API Reference
DriftMonitor
DriftMonitor(
method="ADWIN", # Detection algorithm
sensitivity=0.002, # Drift threshold — lower = more sensitive
min_window=30, # Minimum history before drift can be reported
max_window=10_000, # Maximum records retained in memory
features=None, # List of columns to monitor (None = auto-detect all numeric)
callbacks=None, # List of callables fired on drift
)
Methods
| Method | Description |
|---|---|
monitor.update(data) |
Feed a single row (dict/Series) or micro-batch (DataFrame). Returns DriftResult. |
monitor.reset() |
Reset all internal detector state and history. |
monitor.plot_drift_timeline() |
Render an interactive drift score timeline chart. |
monitor.export_report(path) |
Export full drift history to JSON or CSV. |
monitor.set_reference(data) |
Manually set the reference distribution for comparison. |
DriftMonitor.from_config(path) |
Class method — instantiate from a YAML config file. |
DriftResult Fields
| Field | Type | Description |
|---|---|---|
drift_detected |
bool |
True if drift was found in any monitored feature |
drift_type |
str | None |
sudden · gradual · incremental · recurring |
drifted_features |
list[str] |
Names of all features where drift was detected |
drift_score |
float |
Maximum drift score across all features (0.0–1.0+) |
retraining_window |
RetrainingWindowResult | None |
Suggested retraining window with start, end, n_samples, confidence |
timestamp |
datetime |
UTC datetime when the drift event was recorded |
Alerts & Callbacks
from pattern_drift import DriftMonitor
from pattern_drift.dispatcher import AlertDispatcher
monitor = DriftMonitor(
callbacks=[
AlertDispatcher.slack_callback("https://hooks.slack.com/..."),
AlertDispatcher.webhook_callback("https://my-service/drift"),
AlertDispatcher.log_callback(level="warning"),
lambda result: print(result), # custom inline callback
]
)
YAML Configuration
# drift_config.yaml
method: ADWIN
sensitivity: 0.002
min_window: 30
max_window: 10000
features:
- age
- income
- session_duration
monitor = DriftMonitor.from_config("drift_config.yaml")
scikit-learn Pipeline Integration
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from pattern_drift.sklearn_wrapper import DriftDetector
pipe = Pipeline([
("scaler", StandardScaler()),
("drift", DriftDetector(method="ADWIN", sensitivity=0.002)),
])
pipe.fit(X_train)
for batch in stream:
X_out = pipe.transform(batch) # data passes through unchanged
Visualisation
monitor.plot_drift_timeline() # interactive chart (requires matplotlib)
monitor.export_report("report.json") # or "report.csv"
Architecture
Each incoming record flows through five sequential stages:
- Feature Extractor — splits each row into per-column numeric signals
- Detector Pool — maintains one statistical detector per feature; computes drift score on every update
- Drift Classifier — labels drift as
sudden/gradual/incremental/recurringbased on signal shape - Retraining Window Engine — scans history to find the last stable data window; returns a confidence-scored recommendation
- Alert Dispatcher — fires registered callbacks (Slack, webhook, log, email, or custom)
License
MIT
Metadata
Release files for pattern-drift 0.1.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| pattern_drift-0.1.1.tar.gz | 36.5 kB | Without provenance | Details for pattern_drift-0.1.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| pattern_drift-0.1.1-py3-none-any.whl | Python 3 | none | any | Details for pattern_drift-0.1.1-py3-none-any.whl |
Total release size: 58.2 kB
Release files / pattern_drift-0.1.1.tar.gz
| Download URL | pattern_drift-0.1.1.tar.gz |
|---|---|
| Size | 36.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
890383b71e4acac1811aaae6dcfcc81cbe1aaafa7f40b029fadf3bb58acd3adf
|
|
BLAKE2b-256 checksum How to use checksums |
c0d30cc78e5ab4be7d041beb1b040625b666088565e10f78d2545d38cbef72ac
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / pattern_drift-0.1.1-py3-none-any.whl
| Download URL | pattern_drift-0.1.1-py3-none-any.whl |
|---|---|
| Size | 21.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
252e094f6251321cdc824b976e4155772899693e7fe406a9b0df5cbe4a000b58
|
|
BLAKE2b-256 checksum How to use checksums |
f44325e41ffae414149dc8ba7ce61419d83ee2cb8a564cb0775a3b16157af067
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.10.9 {"installer":{"name":"uv","version":"0.10.9","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for pattern-drift 0.1.1
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
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.