Architettura del progetto
1. Layoutβ
iot-anomaly-detection-clustering/
βββ README.md
βββ LICENSE MIT β Β© 2026 Federico CalΓ²
βββ pyproject.toml Build config + dipendenze
βββ requirements.txt Lock approssimativo
βββ mkdocs.yml Config documentazione (MkDocs Material)
β
βββ .github/
β βββ workflows/
β βββ docs.yml Deploy automatico docs su GitHub Pages
β
βββ src/iot_anomaly/ Libreria Python installabile
β βββ __init__.py
β βββ config.py Path, costanti, iperparametri
β βββ data.py Load + time-aware split
β βββ wrangling.py Missing values per asset
β βββ features.py TimeSeriesFeatureEngineer (rolling, diff, zscore)
β βββ clustering.py KMeans/MiniBatch/GMM + select_k
β βββ scoring.py Distanza centroide + soglia percentile
β βββ evaluation.py Metriche + plot diagnostici
β βββ inference.py detect_anomalies()
β βββ pipeline.py Orchestrator + CLI iot-detect
β
βββ notebooks/ Documentazione esecutiva
β βββ 01_eda.ipynb
β βββ 02_features_pipeline.ipynb
β βββ 03_clustering_threshold.ipynb
β βββ 04_validation_inference.ipynb
β
βββ docs/
β βββ teoria/ 5 file Markdown didattici
β βββ scelte_tecniche/ Architettura, scelte di modello
β
βββ data/raw/ iot_synth_anomaly_clustering.csv (gitignored)
βββ reports/ Output (figures, models, metrics β gitignored)
β βββ figures/
β βββ models/ *.joblib serializzati
β βββ metrics.json
β
βββ scripts/
β βββ build_notebooks.py
β βββ run_full.sh
βββ tests/
2. Principi di designβ
Stesso pattern di ames-housing-price-pipeline:
2.1 Codice in src/, narrativa nei notebookβ
La logica vive in src/iot_anomaly/. I notebook contengono solo importazioni, chiamate, e narrazione didattica. Modifiche al codice si riflettono automaticamente nei notebook (riavvia kernel).
2.2 Notebook generati da scriptβ
scripts/build_notebooks.py Γ¨ la sorgente di veritΓ . Diff Git puliti.
2.3 Pipeline as code (sklearn-compatible)β
Il TimeSeriesFeatureEngineer Γ¨ un BaseEstimator + TransformerMixin. Il modello finale (clustering + scoring + soglia) Γ¨ incapsulato in un AnomalyDetector. L'inferenza ricarica un singolo joblib.
2.4 No leakage by constructionβ
- Wrangling deterministico (ffill/bfill per asset) β puΓ² stare fuori dalla pipeline (non dipende da statistiche).
- Imputazione, scaling, soglia β sempre calcolate sul solo training.
- Rolling back-looking, per asset (
groupby('asset_id')). - Time-aware split, mai casuale.
3. Flusso di esecuzioneβ
3.1 Training completoβ
iot-detect # full run, ~60s
iot-detect --quick # K=5 fisso, ~30s
iot-detect --use-pca # con PCA prima del clustering
iot-detect --threshold-percentile 95 # soglia piΓΉ aggressiva
Sequenza interna:
load_raw()β DataFrame ordinato per (asset, time).add_missing_flags+fill_missing_per_assetβ wrangling.TimeSeriesFeatureEngineerβ rolling, diff, zscore.time_splitβ 7 giorni train / 3 giorni test.StandardScaler+ (opzionale)PCA.select_k_by_silhouettesu K β {3..10}.fit_minibatch_kmeans+fit_anomaly_detector(soglia p99).evaluatesu train e test vsanomaly_labelefault_code_true.- Salvataggio joblib + metriche JSON + figure.
3.2 Inferenzaβ
from iot_anomaly.inference import detect_anomalies
import pandas as pd
df_new = pd.read_csv("nuovi_dati.csv", parse_dates=["timestamp"])
result = detect_anomalies(df_new)
print(result[result.anomaly_pred == 1])
detect_anomalies() riapplica wrangling, FE, scaling, scoring usando gli artefatti serializzati. Output: DataFrame originale + colonne anomaly_score, anomaly_pred.
4. RiproducibilitΓ β
- Stesso dataset: la pipeline carica solo
data/raw/iot_synth_anomaly_clustering.csv. - Stesse versioni:
requirements.txtpinnato a range minor. - Stesso seed:
RANDOM_STATE=42propagato aMiniBatchKMeans,silhouette_score(via sample),KMeans,GMM.
Con stesso ambiente, esecuzioni successive di iot-detect producono metriche bit-identiche.
5. Trade-off esplicitiβ
| Decisione | Vantaggio | Costo |
|---|---|---|
| Time-aware split rigido (7+3) | Realismo | Solo 1 holdout, non K-fold temporale |
| MiniBatchKMeans default | 10Γ piΓΉ veloce di KMeans full | Inertia ~1-3% peggiore |
| Soglia p99 fissa | Configurabile, interpretabile | Non ottimale per ogni asset |
| Niente label nel training | Generalizzazione a anomalie nuove | Performance inferiori vs supervised |
| FE temporale solo rolling+diff+zscore | Interpretabile, veloce | Nessuna feature multivariata (es. cross-correlations) |
6. Estensioni naturaliβ
- GMM con BIC in alternativa a KMeans+silhouette.
- DBSCAN/HDBSCAN per cluster non sferici e detection di noise nativo.
- Soglia per asset: ogni asset ha la sua distribuzione; un percentile globale Γ¨ sub-ottimale.
- Feature multivariate: cross-correlation fra sensori, FFT su finestre brevi.
- Modelli sequenziali (LSTM autoencoder) per collective anomalies.
- Drift detection (KS-test) + retraining schedulato.
- API REST (FastAPI) che espone
detect_anomalies().