🛡️ Vigil
Production-ready unsupervised concept drift detection for network traffic streams
No labels. No manual thresholds. Knows when your data changes — and tells you exactly which features changed.
Install
pip install vigil-drift
The Problem
In production ML systems, the data your model was trained on eventually stops looking like the data it receives — concept drift. For network security, attacks evolve. Most drift detectors require labels (unavailable in real-time) or only tell you that drift happened, not what drifted.
Vigil solves both.
What It Does
| Capability | How |
|---|---|
| 🔍 Detect concept drift | Replicated T-Test (r=15) on autoencoder reconstruction errors — no labels needed |
| 🆕 Identify novel classes | KDE density estimation on a frozen mirror autoencoder (A_KC) |
| 📊 Explain the drift | DriftAttributor ranks input features by reconstruction error delta |
| ⚡ Serve at scale | FastAPI REST service with /fit and /detect endpoints |
| 📡 Stream-native | Kafka producer/consumer pipeline for live network traffic |
| 📈 Track experiments | MLflow logs every chunk's drift severity, novelty, and attribution |
| ✈️ Auto-retrain | Airflow DAGs trigger retraining with quality gate when drift accumulates |
| 🖥️ Visualize live | SOC-style Streamlit dashboard with real-time charts |
Benchmark Results — NSL-KDD
Evaluated on the NSL-KDD dataset (Canadian Institute for Cybersecurity, 125K samples, 22 attack classes).
Setup: trained on 1,000 unlabelled normal traffic samples, evaluated on 50 streaming chunks (10,000 samples total).
| Metric | Result |
|---|---|
| Drift detection Precision | 93.3% |
| Drift detection Recall | 31.1% |
| Drift detection F1 | 46.7% |
| Detection delay | 1 chunk (200 samples) |
| Novel-class detection Recall | 100% |
93.3% precision = near-zero false alarms for SOC teams. 1-chunk delay = attacks caught before lateral movement completes. Fully unsupervised — no attack labels required.
Top drifted features identified: root_shell, service_telnet, service_ecr_i, dst_host_srv_count, dst_host_same_src_port_rate
Reproduce: python benchmark_nsl_kdd.py (auto-downloads NSL-KDD)
Architecture
┌─────────────────────────────────────────────┐
│ Vigil │
│ │
Data Stream │ ┌─────────────┐ ┌─────────────────────┐ │
CSV · Kafka · REST ──► Chunk ─────┼─►│ Autoencoder │──►│ Reconstruction │ │
200 rows │ │ A (adapts) │ │ Errors A │ │ ┌──────────┐
│ │ └─────────────┘ └──────────┬──────────┘ │──►│ MLflow │
│ │ │ │ └──────────┘
│ │ ┌──────────▼──────────┐ │
│ │ │ Replicated T-Test │ │ ┌──────────┐
│ │ │ r=15 α=0.05 ├──┼──►│ FastAPI │
│ │ └──────────┬──────────┘ │ └──────────┘
│ │ │ Drift? │
│ │ ┌──────────▼──────────┐ │ ┌──────────┐
│ │ │ DriftAttributor ├──┼──►│Streamlit │
│ │ │ ★ novel contrib │ │ └──────────┘
│ │ │ ranks Δerror/feat │ │
│ │ └─────────────────────┘ │ ┌──────────┐
│ │ │──►│ Airflow │
│ │ ┌─────────────┐ ┌─────────────────────┐ │ │ DAG │
└────────┼─►│ Autoencoder │──►│ Reconstruction │ │ └──────────┘
│ │ A_KC(frozen)│ │ Errors A_KC │ │
│ └─────────────┘ └──────────┬──────────┘ │
│ ┌──────────▼──────────┐ │
│ │ KDE Novelty │ │
│ │ Detector │ │
│ └─────────────────────┘ │
└─────────────────────────────────────────────┘
Key design decisions (arXiv:2605.29834):
- 1-D reconstruction error proxy → memory O(buffer_size) not O(n × d)
- Dual autoencoders: A adapts on drift; A_KC stays frozen → separates drift from novelty
- Replicated T-tests (r=15) reduce variance vs a single test
Novel contribution (not in the paper):
DriftAttributor— per-feature Δerror → ranks features by drift contribution → makes alerts actionable
Quick Start
from vigil import Vigil
v = Vigil(feature_names=feature_cols, top_k_features=5)
# Phase 1: train on baseline traffic (offline)
v.fit(baseline_data)
# Phase 2: detect on every incoming chunk
for chunk in stream:
result = v.detect(chunk)
if result.drift_detected:
print(f"⚠ severity={result.drift_severity:.2f}")
for feat in result.attribution.top_features:
print(f" {feat['feature_name']}: {feat['contribution']:.1%}")
# ⚠ severity=1.00
# → service_eco_i 15.3% (port scan signature)
# → dst_host_same_src_port_rate 12.3% (scanning pattern)
# → srv_diff_host_rate 11.1% (lateral movement)
Live Dashboard
pip install "vigil-drift[dashboard]"
streamlit run dashboard/app.py
REST API
pip install "vigil-drift[api]"
uvicorn api.app:app --host 0.0.0.0 --port 8000 --reload
# Swagger UI → http://localhost:8000/docs
Kafka Streaming
docker compose up kafka zookeeper -d
python kafka_pipeline/producer.py # publish NSL-KDD chunks
python kafka_pipeline/consumer.py # detect drift in real-time
[Consumer] Chunk 11 [ipsweep] ⚠ DRIFT | severity=1.00
→ service_eco_i(15.3%), dst_host_same_src_port_rate(12.3%)
[Consumer] Chunk 24 [normal] ⚠ DRIFT | severity=0.33
→ root_shell(27.7%), service_telnet(21.5%)
Tests
pytest tests/ -v --cov=vigil
# 14 passed, 81% coverage
Research Basis
Implements and extends:
"Open World Autoencoding Drift Detection with Novel Class Recognition in Tabular Non-stationary Data Streams" arXiv:2605.29834
Links
- GitHub: https://github.com/Venkateswara-Sahu/OWADD
- Website: https://venkateswara-sahu.github.io/OWADD/
- PyPI: https://pypi.org/project/vigil-drift/
MIT © Venkateswara Sahu
Release files for vigil-drift 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| vigil_drift-0.1.3.tar.gz | 27.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| vigil_drift-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 47.9 kB
Release files / vigil_drift-0.1.3.tar.gz
| Download URL | vigil_drift-0.1.3.tar.gz |
|---|---|
| Size | 27.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
47c5c55b9188cfeb0e470cca77847def212b1ece12e79333346f867ef9eba1ea
|
|
BLAKE2b-256 checksum How to use checksums |
06f20167d6a9e59c6cd7438e271dfcca8037a9724d2dc185626999ab0c70f21e
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|
Release files / vigil_drift-0.1.3-py3-none-any.whl
| Download URL | vigil_drift-0.1.3-py3-none-any.whl |
|---|---|
| Size | 20.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
6a5792597c2f943e09bbb67f09b1dbfd03d9af966bb772f739a01e11156144e6
|
|
BLAKE2b-256 checksum How to use checksums |
ecec7d423e509f63ffcaf76f7b1907f42175d8b7a4042f3325265131ec0516df
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.11.9
|