One-Class SVM détection anomalies : Guide complet — Principes, Exemples et Implémentation Python
Résumé
Le One-Class SVM est un algorithme d’apprentissage non supervisé conçu spécifiquement pour la détection d’anomalies. Contrairement aux classifieurs traditionnels qui distinguent plusieurs classes, le One-Class SVM apprend uniquement la frontière englobant les données de la classe normale. Tout échantillon situé en dehors de cette frontière est déclaré anomalie. Cette approche le rend particulièrement puissant dans les scénarios où les exemples anormaux sont rares, inconnus ou non labellisés — un cas extrêmement fréquent dans les applications industrielles réelles.
Dans ce guide, nous explorerons les principes mathématiques du One-Class SVM, son intuition fondamentale, son implémentation pratique avec scikit-learn, l’influence de ses hyperparamètres, ainsi que quatre cas d’usage concrets en production.
Principe mathématique
Le One-Class SVM, introduit par Schölkopf et ses collaborateurs en 2001, repose sur les machines à vecteurs de support (SVM) classiques. Le problème fondamental est le suivant : trouver l’hyperplan optimal qui sépare les données de l’origine dans un espace de features de grande dimension.
Formulation d’optimisation
Le problème primal du One-Class SVM s’écrit comme suit :
min (1/2) ||w||² - ρ + 1/(ν·n) Σ ξ_i
sous les contraintes :
w · φ(x_i) ≥ ρ - ξ_i, ∀i
ξ_i ≥ 0, ∀i
Où :
- w est le vecteur normal à l’hyperplan dans l’espace de features.
- φ(xᵢ) représente la transformation non linéaire des données d’entrée via une fonction de noyau (kernel).
- ρ est le biais (ou marge) qui détermine la distance de l’hyperplan par rapport à l’origine.
- ξᵢ sont des variables d’écart (slack variables) qui autorisent certaines violations de la contrainte, permettant ainsi une frontière plus souple.
- ν (nu) est le paramètre clé qui contrôle la fraction maximum d’anomalies tolérée et la fraction minimum de vecteurs de support.
Le rôle du noyau (kernel)
Comme les SVM classiques, le One-Class SVM utilise l’astuce du noyau (kernel trick) pour projeter implicitement les données dans un espace de plus grande dimension. Le noyau RBF (Radial Basis Function) est le plus couramment employé :
K(xᵢ, xⱼ) = exp(-γ ||xᵢ - xⱼ||²)
Le paramètre γ (gamma) détermine la largeur de la gaussienne et influence directement la souplesse de la frontière décisionnelle. Un gamma élevé produit une frontière très flexible qui peut capturer des structures complexes, tandis qu’un gamma faible génère une frontière plus régulière et plus généralisante.
Fonction de décision
Une fois le modèle entraîné, la fonction de décision pour un échantillon x s’écrit :
f(x) = signe(Σ αᵢ K(xᵢ, x) - ρ)
Si f(x) = +1, l’échantillon est classé comme normal. Si f(x) = -1, il est classé comme anomalie. La valeur continue decision_function(x) permet d’obtenir un score de normalité : plus le score est élevé, plus le point est au cœur de la distribution normale.
Intuition géométrique
Plutôt que d’essayer de distinguer plusieurs classes les unes des autres, le One-Class SVM adopte une stratégie radicalement différente : il apprend ce qui est normal en entourant les données d’entraînement avec une frontière aussi compacte que possible.
Imaginez un nuage de points sur un plan. Le One-Class SVM va dessiner une frontière autour de ce nuage. Cette frontière épouse la forme du nuage grâce au noyau RBF — elle n’est pas nécessairement circulaire ou elliptique. Tout point situé à l’extérieur de cette frontière est déclaré suspect, car il ne ressemble pas aux échantillons normaux observés pendant l’entraînement.
Cette approche est particulièrement pertinente lorsque :
- Les anomalies sont rares et donc difficiles à collecter pour l’entraînement.
- Les anomalies sont imprévisibles — leur nature peut évoluer dans le temps.
- Nous ne disposons que d’exemples positifs (données normales) sans étiquettes négatives.
Le paramètre ν joue le rôle de thermostat : une valeur faible (ν = 0,01) impose une frontière stricte qui tolère peu d’erreurs (risque de faux positifs accru), tandis qu’une valeur élevée (ν = 0,5) admet une frontière plus permissive.
Implémentation Python avec scikit-learn
Exemple fondamental : détection d’anomalies sur des blobs
Voici une implémentation complète utilisant OneClassSVM de scikit-learn :
import numpy as np
import matplotlib.pyplot as plt
from sklearn.svm import OneClassSVM
from sklearn.datasets import make_blobs
from sklearn.ensemble import IsolationForest
from sklearn.metrics import classification_report
# --- 1. Génération des données ---
# Données normales : deux blobs gaussiens
X_normal, _ = make_blobs(
n_samples=500, centers=2,
cluster_std=0.8, random_state=42
)
# Anomalies artificielles : points uniformément répartis
np.random.seed(42)
X_outliers = np.random.uniform(
low=-8, high=8, size=(50, 2)
)
# Jeu d'entraînement (uniquement des données normales)
X_train = X_normal
# Jeu de test (mélange normal + anomalies)
X_test = np.vstack([X_normal, X_outliers])
y_true = np.concatenate([
np.ones(len(X_normal)),
-np.ones(len(X_outliers))
])
# --- 2. Entraînement du One-Class SVM ---
ocsvm = OneClassSVM(
kernel='rbf', gamma=0.1, nu=0.05
)
ocsvm.fit(X_train)
# Prédictions
y_pred = ocsvm.predict(X_test)
print("Classification Report (One-Class SVM) :")
print(classification_report(
y_true, y_pred,
target_names=['Anomalie', 'Normal']
))
# --- 3. Visualisation de la frontière ---
xx, yy = np.meshgrid(
np.linspace(-8, 8, 200),
np.linspace(-8, 8, 200)
)
Z = ocsvm.decision_function(
np.c_[xx.ravel(), yy.ravel()]
)
Z = Z.reshape(xx.shape)
plt.figure(figsize=(10, 7))
plt.contourf(
xx, yy, Z, levels=np.linspace(Z.min(), 0, 50),
cmap='Blues', alpha=0.7
)
plt.contour(xx, yy, Z, levels=[0], colors='red', linewidths=2)
normal_mask = (y_pred == 1)
outlier_mask = (y_pred == -1)
plt.scatter(
X_test[normal_mask, 0], X_test[normal_mask, 1],
c='steelblue', s=30, label='Normal', alpha=0.7
)
plt.scatter(
X_test[outlier_mask, 0], X_test[outlier_mask, 1],
c='red', s=50, marker='x', label='Anomalie',
linewidths=2, alpha=0.9
)
plt.title(
"One-Class SVM : frontière de décision et "
"détection d'anomalies"
)
plt.xlabel("Feature 1")
plt.ylabel("Feature 2")
plt.legend()
plt.tight_layout()
plt.show()
Comparaison avec Isolation Forest
Il est instructif de comparer le One-Class SVM avec l’Isolation Forest, un autre algorithme phare de détection d’anomalies :
# Isolation Forest pour comparaison
iforest = IsolationForest(
contamination=0.05, random_state=42
)
iforest.fit(X_train)
y_pred_if = iforest.predict(X_test)
print("\nClassification Report (Isolation Forest) :")
print(classification_report(
y_true, y_pred_if,
target_names=['Anomalie', 'Normal']
))
# Visualisation comparative
Z_if = iforest.decision_function(
np.c_[xx.ravel(), yy.ravel()]
)
Z_if = Z_if.reshape(xx.shape)
fig, axes = plt.subplots(1, 2, figsize=(16, 6))
for ax, Z_val, title in [
(axes[0], Z, "One-Class SVM"),
(axes[1], Z_if, "Isolation Forest")
]:
ax.contourf(xx, yy, Z_val, levels=40, cmap='coolwarm', alpha=0.7)
ax.contour(xx, yy, Z_val, levels=[0], colors='black', linewidths=2)
ax.scatter(
X_test[y_true == 1, 0], X_test[y_true == 1, 1],
c='steelblue', s=20, label='Normal', alpha=0.5
)
ax.scatter(
X_test[y_true == -1, 0], X_test[y_true == -1, 1],
c='red', s=60, marker='x', linewidths=2,
label='Anomalie réelle'
)
ax.set_title(title)
ax.legend()
plt.suptitle(
"Comparaison des frontières de décision"
)
plt.tight_layout()
plt.show()
Interprétation de la fonction de décision
La méthode decision_function() retourne un score continu extrêmement utile :
scores = ocsvm.decision_function(X_test)
# Distribution des scores
plt.figure(figsize=(10, 5))
plt.hist(
scores[y_true == 1], bins=50, alpha=0.6,
color='steelblue', label='Distribution normale'
)
plt.hist(
scores[y_true == -1], bins=30, alpha=0.6,
color='red', label='Anomalies'
)
plt.axvline(x=0, color='black', linestyle='--',
linewidth=1.5, label='Seuil = 0')
plt.xlabel("Score de décision")
plt.ylabel("Fréquence")
plt.title(
"Distribution des scores de décision : "
"One-Class SVM"
)
plt.legend()
plt.tight_layout()
plt.show()
Ce graphique révèle typiquement une distribution bimodale : un pic large pour les points normaux (scores positifs) et un pic étroit pour les anomalies (scores négatifs). Le seuil de 0 constitue la frontière entre les deux régions.
Hyperparamètres du One-Class SVM
La performance du One-Class SVM dépend fortement du réglage de ses hyperparamètres. Voici une analyse détaillée de chacun :
kernel
Le noyau définit la transformation implicite de l’espace d’entrée :
- “rbf” : le choix par défaut et le plus utilisé. Adapte la frontière à des formes complexes.
- “linear” : frontière linéaire dans l’espace d’origine. Rapide mais limité en expressivité.
- “poly” : noyau polynomial. Utile lorsque les données présentent des interactions polynomiales.
- “sigmoid” : noyau sigmoïde, inspiré des réseaux de neurones. Rarement utilisé en pratique.
nu
Paramètre le plus critique. Il contrôle un compromis entre deux bornes théoriques :
- Borne supérieure : fraction maximale d’échantillons classés comme anomalies.
- Borne inférieure : fraction minimale de vecteurs de support.
En pratique, ν ≈ 0,01 à 0,1 fonctionne bien pour des données où les anomalies constituent 1 % à 10 % du volume. Un ν de 0,05 signifie qu’environ 5 % des données d’entraînement seront classées comme anomalies.
gamma
Le paramètre gamma du noyau RBF :
gamma = 1 / (2 × σ²)
- Gamma faible : frontière souple, bonne généralisation mais risque de sous-apprentissage.
- Gamma élevé : frontière très flexible, peut capturer des détails fins mais risque de surapprentissage.
- Règle pratique :
gamma='auto'utilise 1/n_features, mais il est souvent nécessaire de valider par cross-validation.
degree
Degré du noyau polynomial. N’est pertinent que lorsque kernel='poly'. La valeur par défaut est 3. Des degrés supérieurs augmentent la capacité du modèle à modéliser des interactions complexes, mais au prix d’une complexité computationnelle accrue.
shrinking
Active l’optimisation par réduction (shrinking heuristics). Accélère significativement l’entraînement, surtout sur les grands jeux de données. La valeur par défaut est True. Il est rarement nécessaire de la désactiver.
cache_size
Taille du noyau en mémoire cache (en Mo). La valeur par défaut est 200 Mo. L’augmenter (par exemple à 500 Mo) peut accélérer l’entraînement sur les grands jeux, au prix d’une consommation mémoire plus élevée.
tol
Tolérance pour le critère d’arrêt. Par défaut : 1e-3. Une tolérance plus stricte (1e-4) assure une convergence plus précise mais prolonge l’entraînement.
Avantages et Limites
Avantages
- Pas besoin d’anomalies labellisées : Fonctionne uniquement avec des exemples normaux.
- Frontières non linéaires : Le noyau RBF capture des formes complexes.
- Fondement théorique solide : Dérivé de la théorie des SVM, avec garanties de convergence.
- Score continu : La
decision_functionpermet d’ajuster le seuil selon le métier. - Vecteurs de support : Seuls les points proches de la frontière sont stockés en mémoire, ce qui rend l’inférence efficace.
Limites
- Complexité computationnelle : L’entraînement est en O(n²) à O(n³), prohibitif au-delà de ~50 000 échantillons.
- Sensibilité aux hyperparamètres : Le réglage de nu et gamma est critique et nécessite une validation minutieuse.
- Difficile à interpréter : La frontière dans l’espace de features n’est pas directement visualisable en haute dimension.
- Mémoire : Les vecteurs de support doivent être conservés pour l’inférence, ce qui peut être coûteux.
- Pas de probabilités : Ne retourne pas de probabilités d’appartenance nativement (nécessite un calibrage supplémentaire).
4 Cas d’usage concrets
Cas 1 : Détection de fraude financière
Dans les transactions bancaires, la fraude représente généralement moins de 0,1 % du volume. Le One-Class SVM est entraîné sur des mois de transactions légitimes. Chaque nouvelle transaction est évaluée par la fonction de décision : un score négatif déclenche une alerte pour investigation manuelle. Le paramètre ν est réglé pour limiter les faux positifs qui satureraient les équipes d’analyse.
Cas 2 : Maintenance prédictive industrielle
Les capteurs d’une machine industrielle génèrent des séries temporelles de vibrations, température et pression. Le One-Class SVM modélise le comportement normal de l’équipement en fonctionnement sain. Une déviation de la frontière normale signale une usure précoce, une défaillance imminente ou un besoin de maintenance, permettant ainsi d’intervenir avant la panne.
Cas 3 : Cybersécurité — Détection d’intrusions
Le trafic réseau d’un système d’information présente des patterns reconnaissables : volumes de données, horaires, protocoles utilisés. Le One-Class SVM apprend ce trafic légitime. Une attaque zero-day, par définition inconnue des signatures classiques, se manifeste par un écart par rapport au comportement normal et est ainsi détectée — même sans signature préalable.
Cas 4 : Contrôle qualité de fabrication
Dans une chaîne de production, les pièces défectueuses suivent des distributions de mesures (dimensions, poids, résistance) différentes des pièces conformes. Le One-Class SVM, entraîné sur les mesures des pièces acceptées, identifie automatiquement les pièces dont les caractéristiques s’écartent de la distribution normale, permettant un tri en temps réel sur la chaîne.
Voir aussi
- Implémentez l’algorithme de hachage SHA-1 en Python : Guide étape par étape
- Tracer un Triangle avec des Arcs de Cercle en Python : Guide Complet pour les Développeurs

