Spaces:
Sleeping
Sleeping
| title: Real-Time Anomaly Detection | |
| emoji: 📡 | |
| colorFrom: blue | |
| colorTo: indigo | |
| sdk: docker | |
| app_port: 7860 | |
| pinned: false | |
| # Real-Time Anomaly Detection on Time-Series Streams | |
| **Live demo: [anomaly.zeetay.dev](https://anomaly.zeetay.dev)** | |
| Online anomaly detection on a multivariate sensor stream with concept drift handling. Each observation is scored once as it arrives. No batch retraining. | |
| ## Problem | |
| Sensor distributions shift over time. A static model will either miss anomalies in the new regime or start flagging normal post-drift readings as anomalous. This project fits a baseline during a stable warmup window, then scores every subsequent observation against it while monitoring for distribution shifts. | |
| ## Approach | |
| - **Synthetic stream**: Three-phase generator (normal baseline, gradual drift, injected anomalies) with configurable rates and ground truth labels. | |
| - **Online scorer**: Mahalanobis distance from a frozen Phase A baseline. Uses the full sensor covariance matrix, so it catches contextual anomalies (anti-correlated sensor readings) that per-feature z-score methods miss entirely. | |
| - **Drift detection**: ADWIN watches a normalized composite sensor signal. When the distribution shifts (Phase B), ADWIN fires. The anomaly baseline is kept since it was calibrated before drift started. | |
| - **Running metrics**: Precision, recall, and F1 are updated after every observation against ground truth labels. | |
| - **Real-time UI**: FastAPI + WebSocket streams each scored observation to a dashboard with rolling charts, anomaly/drift markers, and live counters. New visitors get a replay of the last 200 points. | |
| ## Results (offline benchmark) | |
| Evaluated on Phase C (300 obs, 10% anomaly rate, seed=42): | |
| | Method | Precision | Recall | F1 | Mode | | |
| |--------|-----------|--------|-----|------| | |
| | Mahalanobis + ADWIN | 0.833 | 1.000 | **0.909** | online | | |
| | Isolation Forest | 0.476 | 1.000 | 0.645 | batch | | |
| | Z-Score (max \|z\|>2.5) | 0.450 | 0.600 | 0.514 | batch | | |
| Z-Score's recall is limited by contextual anomalies where no single sensor exceeds the 2.5σ threshold. Mahalanobis catches these via the covariance term. | |
| ## Tech stack | |
| - **Python 3.10+** | |
| - **River** - online drift detection (ADWIN) | |
| - **numpy / scikit-learn** - Mahalanobis scoring, Isolation Forest baseline | |
| - **FastAPI** - REST + WebSocket, static dashboard | |
| - **asyncio** - async stream and pipeline | |
| - **pytest** - tests for stream, detector, pipeline, and server | |
| ## Setup and run | |
| ```bash | |
| python -m venv .venv | |
| .venv\Scripts\activate # Windows | |
| # source .venv/bin/activate # Linux/macOS | |
| pip install -r requirements.txt | |
| python run.py | |
| ``` | |
| Open **http://localhost:8000/**. The pipeline starts on first connection and loops automatically. | |
| ## Deploy | |
| - **Frontend**: [anomaly.zeetay.dev](https://anomaly.zeetay.dev) — Netlify, auto-deploys from `main` | |
| - **Backend**: [huggingface.co/spaces/zeetay/anomaly-detection](https://huggingface.co/spaces/zeetay/anomaly-detection) — HF Spaces (Docker) | |
| The frontend is static files served by Netlify. The backend is a FastAPI + WebSocket server running in a Docker container on HF Spaces. `dashboard.js` connects directly to the HF Space WebSocket from any non-HF host. | |
| **Docker locally:** `docker build -t anomaly . && docker run -p 7860:7860 anomaly` | |
| ## Tests | |
| ```bash | |
| pytest | |
| ``` | |
| All tests use the synthetic stream and need no external services. | |
| ## Project layout | |
| | Path | Role | | |
| |------|------| | |
| | `src/stream/` | Observation model, async synthetic generator (phases A/B/C) | | |
| | `src/detector/` | Anomaly scorer (Mahalanobis), drift detector (ADWIN), running metrics | | |
| | `src/pipeline/` | Async pipeline: stream, score, broadcast, replay buffer | | |
| | `src/server/` | FastAPI app, WebSocket, `/stats`, `/metrics` (Prometheus), static dashboard | | |
| | `tests/` | Pytest for stream, detector, pipeline, dashboard | | |
| ## Design notes | |
| - **Mahalanobis over Z-Score**: Z-Score tests each sensor independently. Mahalanobis uses the covariance matrix, so readings that look moderate in isolation but are unusual as a combination (e.g., temp up + pressure down when they normally move together) score high. | |
| - **ADWIN on sensor signal, not anomaly scores**: Watching the normalized sensor deviation catches sustained distribution shifts without false-firing on isolated anomaly spikes. | |
| - **Replay on connect**: New clients get the last 200 messages immediately, then live updates. | |
| - **Start on first connect**: The pipeline only runs while at least one client is connected. Counters reset each cycle. | |