🧠 AI / ML

ai-ml-anomaly-detection-builder

Conception de systèmes de détection d'anomalies (statistique, ML, deep learning) — arbre de décision, snippets copiables, anti-patterns, déploiement production

⚡ Installation & lancement en 1 commande

Copiez-collez dans votre terminal : le skill s'installe dans ~/.claude/skills et Claude Code se lance directement dessus.

macOS / Linux
curl -fsSL https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.sh | sh -s -- ai-ml-anomaly-detection-builder --launch
Windows (PowerShell)
iex "& { $(iwr -useb https://raw.githubusercontent.com/khalilbenaz/claude-skills-collection/main/install.ps1) } ai-ml-anomaly-detection-builder -Launch"

🚀 Déjà installé ?

claude "/ai-ml-anomaly-detection-builder"

Ou tapez /ai-ml-anomaly-detection-builder dans une session Claude Code, ou décrivez simplement votre besoin — le skill se déclenche automatiquement via le skill-router.

📦 Installation manuelle

git clone https://github.com/khalilbenaz/claude-skills-collection.git cp -r claude-skills-collection/skills/ai-ml-anomaly-detection-builder ~/.claude/skills/

Payload du plugin : skills/ai-ml-anomaly-detection-builder · source éditable : ai-ml-skills/anomaly-detection-builder

📖 Manuel

Anomaly Detection Builder

1. Caractériser le problème

Questions clés avant de coder quoi que ce soit :

DimensionOptionsImpact sur le choix technique
Type d'anomaliePonctuelle / Contextuelle / CollectiveContextuelle → features temporelles obligatoires
Disponibilité des labelsSupervisé / Semi-supervisé / Non-superviséLabels → classifier classique suffit souvent
Ratio d'anomalies< 0.1 % / 0.1–5 % / > 5 %< 0.1 % → isolation/reconstruction ; > 5 % → SMOTE + classifier
Contrainte de latenceTemps réel (< 100 ms) / Batch (minutes)Temps réel → éviter DBSCAN, LOF sur grands datasets
Coût faux négatif vs faux positifFraude / Qualité / InfraCalibre le seuil, pas le modèle

2. Arbre de décision : choisir la méthode

Données labellisées suffisantes ?
├─ OUI → XGBoost / LightGBM avec class_weight + seuil F1-optimal
│         (baseline solide, explicable, rapide)
└─ NON
    ├─ Données tabulaires basses dimensions (< 50 features) ?
    │   └─ Isolation Forest  (2–5 M lignes sans GPU)
    │       si résultats insuffisants → One-Class SVM (kernel RBF)
    ├─ Séries temporelles ?
    │   ├─ Courte fenêtre (< 1 h) → SARIMA residuals ou STL decomposition
    │   └─ Longue séquence → LSTM Autoencoder ou Transformer (TadGAN, Anomaly Transformer)
    ├─ Images / texte ?
    │   └─ Autoencoder convolutif ou VAE + seuil sur reconstruction error
    └─ Logs / événements discrets ?
        └─ Drain3 (log parsing) → Isolation Forest sur vecteurs TF-IDF

3. Préparer les données

import pandas as pd
from sklearn.preprocessing import RobustScaler

df = pd.read_parquet("data/raw.parquet")

# 1. Statistiques glissantes (features temporelles)
for w in [5, 30, 60]:  # minutes
    df[f"mean_{w}m"] = df["value"].rolling(w).mean()
    df[f"std_{w}m"]  = df["value"].rolling(w).std()

# 2. Ratios / deltas — souvent plus discriminants que la valeur brute
df["pct_change"] = df["value"].pct_change()
df["z_score"]    = (df["value"] - df["value"].rolling(60).mean()) / df["value"].rolling(60).std()

# 3. Normalisation robuste (insensible aux outliers existants)
scaler = RobustScaler()
X = scaler.fit_transform(df[features].dropna())

Pièges fréquents en préparation :


4. Implémenter le détecteur

Isolation Forest (point de départ universel)

from sklearn.ensemble import IsolationForest

model = IsolationForest(
    n_estimators=200,       # 100 suffit rarement sur > 100k lignes
    contamination=0.01,     # estimation du ratio d'anomalies attendu
    max_samples="auto",
    random_state=42,
    n_jobs=-1,
)
model.fit(X_train)

scores = -model.score_samples(X_test)  # plus élevé = plus anormal

LSTM Autoencoder (séries temporelles)

import torch, torch.nn as nn

class LSTMAutoencoder(nn.Module):
    def __init__(self, n_features, hidden=64, latent=16):
        super().__init__()
        self.encoder = nn.LSTM(n_features, hidden, batch_first=True)
        self.bottleneck = nn.Linear(hidden, latent)
        self.expand     = nn.Linear(latent, hidden)
        self.decoder    = nn.LSTM(hidden, n_features, batch_first=True)

    def forward(self, x):
        enc_out, _ = self.encoder(x)
        h = torch.relu(self.bottleneck(enc_out))
        h = torch.relu(self.expand(h))
        dec_out, _ = self.decoder(h)
        return dec_out

# Score = MSE de reconstruction par séquence
recon_error = ((x_test - model(x_test)) ** 2).mean(dim=(1, 2))

Baseline statistique (toujours comparer)

# Z-score sur fenêtre glissante — souvent suffisant pour séries univariées
def zscore_anomaly(series, window=60, threshold=3.0):
    mu  = series.rolling(window).mean()
    std = series.rolling(window).std()
    z   = (series - mu) / (std + 1e-9)
    return z.abs() > threshold

5. Calibrer le seuil

Le seuil est aussi critique que le modèle.

from sklearn.metrics import precision_recall_curve, f1_score
import numpy as np

# Si labels disponibles : maximiser F1 ou recall à precision minimale acceptable
precision, recall, thresholds = precision_recall_curve(y_true, scores)
min_precision = 0.30  # tolérance aux faux positifs
mask = precision[:-1] >= min_precision
best_threshold = thresholds[mask][recall[:-1][mask].argmax()]

# Si pas de labels : percentile métier
threshold = np.percentile(scores, 99)   # top 1 % des scores

Tableau d'aide au choix de stratégie :

Contrainte métierStratégie recommandée
Aucune fausse alerte toléréeMaximize precision à recall ≥ 0.5
Aucune anomalie manquée (fraude, sécurité)Maximize recall à precision ≥ 0.2
Équilibre opérationnelMaximize F1 ou F-beta (beta > 1 pour recall)
Pas de labelsPercentile ou sigma-rule, ajuster via feedback

6. Évaluer correctement

from sklearn.metrics import (
    classification_report, average_precision_score, roc_auc_score
)

y_pred = (scores >= best_threshold).astype(int)

print(classification_report(y_true, y_pred))
print("AUC-PR :", average_precision_score(y_true, scores))
print("AUC-ROC:", roc_auc_score(y_true, scores))

Métriques indispensables :

Ne jamais utiliser l'accuracy seule. Avec 1 % d'anomalies, prédire "normal" partout donne 99 % d'accuracy.


7. Déployer en production

# Inférence temps réel via une file (ex : Kafka consumer)
import joblib, json
from kafka import KafkaConsumer

model   = joblib.load("isolation_forest.pkl")
scaler  = joblib.load("scaler.pkl")

consumer = KafkaConsumer("events", bootstrap_servers="broker:9092",
                         value_deserializer=lambda m: json.loads(m.decode()))

for msg in consumer:
    x       = scaler.transform([extract_features(msg.value)])
    score   = -model.score_samples(x)[0]
    if score > THRESHOLD:
        send_alert(severity="critical" if score > THRESHOLD * 1.5 else "warning",
                   payload=msg.value, score=score)

Checklist déploiement :


8. Monitorer et itérer

# Calculer le Population Stability Index (PSI) pour détecter le drift
def psi(expected, actual, buckets=10):
    def scale(x):
        counts, _ = np.histogram(x, bins=buckets)
        return (counts + 1e-9) / len(x)  # éviter division par 0
    e, a = scale(expected), scale(actual)
    return np.sum((a - e) * np.log(a / e))

psi_score = psi(scores_train, scores_production_last_week)
# PSI > 0.2 → recalibration urgente ; 0.1–0.2 → surveiller

Fréquence de recalibration recommandée :


Anti-patterns et garde-fous

Anti-patternConséquenceCorrection
Scaler fitté sur tout le datasetData leakage, faux bons résultatsFit scaler uniquement sur train
Contamination Isolation Forest = 0.5 par défautTrop d'anomalies détectéesEstimer le vrai ratio ou utiliser score_samples + seuil manuel
Évaluer uniquement sur accuracyIgnorer toutes les vraies anomaliesAUC-PR obligatoire
Threshold codé en dur sans monitoringDérive silencieuse en prodPSI + recalibration périodique
Un seul détecteur en productionPoint de défaillance uniqueEnsemble : vote majoritaire sur 2-3 détecteurs
Entraîner avec anomalies dans le set (semi-supervisé)Modèle apprend à ne pas les détecterNettoyer le train set des anomalies connues
Négliger l'heure/jour comme featureFaux positifs sur trafic nuit/weekendAjouter features calendaires systématiquement

Bibliothèques clés (2026)

pip install scikit-learn pyod river           # classiques + streaming
pip install torch torchmetrics               # deep learning
pip install alibi-detect                     # drift + outlier + adversarial
pip install stumpy                           # matrix profile (séries temporelles)
pip install drain3                           # parsing de logs