Polydesk-logotype
Polydesk.ai — Header

Courbe ROC (Receiver Operating Characteristic)

La courbe ROC (Receiver Operating Characteristic) est un graphique qui trace le taux de vrais positifs (sensibilité) en fonction du taux de faux positifs (1 – spécificité) pour chaque seuil de décision possible d’un classifieur binaire.

Elle permet de visualiser le compromis entre détecter les positifs et générer de fausses alertes, quel que soit le seuil choisi. Un modèle parfait produit une courbe qui monte immédiatement vers le coin supérieur gauche. Un modèle aléatoire produit une diagonale. L’aire sous cette courbe, appelée AUC, résume la performance globale en un seul chiffre entre 0 et 1.

Née pendant la Seconde Guerre mondiale pour optimiser la détection radar, la courbe ROC est devenue l’outil standard d’évaluation des modèles de classification binaire en machine learning, en médecine et en data science.

Fiche rapide : Courbe ROC
Nom complet
Receiver Operating Characteristic Curve
Axe X
FPR (False Positive Rate) = FP / (FP + TN)
Axe Y
TPR (True Positive Rate) = TP / (TP + FN)
Point idéal
(0, 1) : aucun faux positif, 100 % de vrais positifs
Métrique dérivée
AUC-ROC (aire sous la courbe)
Calcul Python
sklearn.metrics.roc_curve() + RocCurveDisplay
Origine
Détection radar, Seconde Guerre mondiale (1941)

Origine historique : du radar au machine learning

L’histoire de la courbe ROC commence après l’attaque de Pearl Harbor en 1941. L’armée américaine a lancé un programme de recherche pour améliorer la capacité des opérateurs radar à distinguer les avions ennemis du bruit de fond (nuages, vols d’oiseaux, interférences). Le problème fondamental était un compromis : augmenter la sensibilité du récepteur détectait plus d’avions réels, mais aussi plus de fausses alertes.

Les ingénieurs ont formalisé ce compromis sous forme de courbe, en traçant la probabilité de détection correcte contre la probabilité de fausse alarme pour différents réglages du récepteur. D’où le nom : « Receiver Operating Characteristic », la caractéristique de fonctionnement du récepteur.

La première publication formelle est attribuée à Peterson, Birdsall et Fox en 1954 dans les Transactions of the IRE Professional Group on Information Theory. Dans les années 1950, la méthode a migré vers la psychophysique (détection de stimuli faibles), puis vers la médecine dans les années 1960-1970, où elle est devenue l’outil de référence pour évaluer les tests diagnostiques. L’article fondateur de Hanley et McNeil (1982) dans Radiology a posé les bases de l’utilisation de l’AUC comme mesure résumée. Enfin, Spackman (1989) a introduit la courbe ROC en machine learning pour comparer des algorithmes de classification.

Les composantes fondamentales de la courbe ROC

Pour comprendre la courbe ROC, il faut maîtriser les quatre métriques élémentaires issues de la matrice de confusion.

Rappel : la matrice de confusion

Pour un seuil donné, chaque prédiction tombe dans l’une de quatre catégories :

Prédit Positif Prédit Négatif
Réel Positif Vrai Positif (TP) Faux Négatif (FN)
Réel Négatif Faux Positif (FP) Vrai Négatif (TN)

TPR et FPR : les deux axes de la courbe

Le TPR (True Positive Rate), aussi appelé sensibilité, rappel ou taux de détection, mesure la proportion de positifs réels correctement identifiés : TPR = TP / (TP + FN). C’est la question : « parmi tous les cas positifs, combien le modèle en a-t-il trouvé ? »

Le FPR (False Positive Rate), aussi appelé taux de fausse alarme ou (1 – spécificité), mesure la proportion de négatifs réels incorrectement classés comme positifs : FPR = FP / (FP + TN). C’est la question : « parmi tous les cas négatifs, combien le modèle a-t-il mal classé ? »

Ces deux métriques sont complémentaires. Le TPR vous dit à quel point le modèle est bon pour trouver les positifs. Le FPR vous dit quel « prix » vous payez en fausses alertes. La courbe ROC visualise ce compromis pour chaque seuil possible.

Lien avec sensibilité et spécificité

En médecine, on utilise plutôt les termes sensibilité (= TPR) et spécificité (= 1 – FPR = TN / (TN + FP)). La courbe ROC peut être vue comme un graphique de sensibilité vs (1 – spécificité). Les deux formulations sont strictement équivalentes. En ML, on préfère TPR/FPR. En épidémiologie, on préfère sensibilité/spécificité. Les courbes sont identiques.

Comment construire une courbe ROC étape par étape

La construction d’une courbe ROC suit un processus systématique. Prenons un exemple concret avec 8 observations.

Étape 1 : Obtenir les scores de prédiction

Votre modèle de classification produit un score de probabilité pour chaque observation. Par exemple, un modèle de détection de spam attribue à chaque email une probabilité d’être du spam.

Email Score prédit Classe réelle
A0,95Spam
B0,85Spam
C0,72Légitime
D0,60Spam
E0,45Légitime
F0,30Légitime
G0,18Spam
H0,05Légitime

Étape 2 : Faire varier le seuil

Pour chaque seuil possible (de 1,0 vers 0,0), vous classez chaque observation comme positive (score ≥ seuil) ou négative (score < seuil), puis vous calculez le TPR et le FPR correspondants.

Au seuil 1,0 : rien n’est classé positif → TPR = 0, FPR = 0. Point (0, 0).

Au seuil 0,90 : seul A est classé spam → 1 TP sur 4 positifs réels, 0 FP sur 4 négatifs réels → TPR = 0,25, FPR = 0. Point (0, 0,25).

Au seuil 0,70 : A, B, C classés spam → 2 TP, 1 FP → TPR = 0,50, FPR = 0,25. Point (0,25, 0,50).

Et ainsi de suite jusqu’au seuil 0,0 : tout est classé positif → TPR = 1, FPR = 1. Point (1, 1).

Étape 3 : Tracer les points

Chaque paire (FPR, TPR) produit un point. En reliant tous les points, vous obtenez la courbe ROC. Plus la courbe se rapproche du coin supérieur gauche (0, 1), meilleur est le modèle.

Les formes typiques de courbes ROC

Classifieur parfait

La courbe monte verticalement de (0, 0) à (0, 1) puis s’étend horizontalement jusqu’à (1, 1), formant un angle droit. L’AUC vaut 1,0. Il existe au moins un seuil où le modèle sépare parfaitement les deux classes sans aucune erreur. En pratique, c’est extrêmement rare sur des données réelles et doit faire suspecter une fuite de données (overfitting ou data leakage).

Bon modèle

La courbe passe nettement au-dessus de la diagonale, formant un arc convexe vers le coin supérieur gauche. L’AUC est typiquement entre 0,80 et 0,95. C’est le profil d’un modèle exploitable en production.

Classifieur aléatoire

La courbe suit (approximativement) la diagonale de (0, 0) à (1, 1). L’AUC vaut 0,5. Le modèle n’a rien appris : il ne fait pas mieux qu’un tirage au sort. C’est la baseline de référence.

Classifieur inversé

La courbe passe en dessous de la diagonale (AUC < 0,5). Le modèle classe systématiquement à l'envers. Inverser ses prédictions donnerait immédiatement un AUC supérieur à 0,5.

Courbes qui se croisent Deux modèles peuvent avoir des courbes ROC qui se croisent : l’un domine à faible FPR, l’autre à FPR élevé. Dans ce cas, l’AUC globale ne suffit pas pour choisir. Il faut identifier la zone de FPR pertinente pour votre cas d’usage et comparer les courbes dans cette zone spécifique.

Tracer une courbe ROC en Python

Méthode classique avec roc_curve

Scikit-learn (version 1.8 au moment de la rédaction) fournit roc_curve() pour calculer les points de la courbe et auc() pour calculer l’aire :

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import roc_curve, auc

# Données d'exemple
y_true = np.array([1, 1, 0, 1, 0, 0, 1, 0])
y_scores = np.array([0.95, 0.85, 0.72, 0.60, 0.45, 0.30, 0.18, 0.05])

# Calcul de la courbe ROC
fpr, tpr, thresholds = roc_curve(y_true, y_scores)
roc_auc = auc(fpr, tpr)

# Tracé
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='#7c3aed', lw=2,
         label=f'Modèle (AUC = {roc_auc:.2f})')
plt.plot([0, 1], [0, 1], 'k--', lw=1,
         label='Aléatoire (AUC = 0.50)')
plt.fill_between(fpr, tpr, alpha=0.1, color='#7c3aed')
plt.xlabel('Taux de faux positifs (FPR)')
plt.ylabel('Taux de vrais positifs (TPR)')
plt.title('Courbe ROC')
plt.legend(loc='lower right')
plt.grid(alpha=0.3)
plt.tight_layout()
plt.show()

La fonction roc_curve() renvoie trois tableaux : les valeurs de FPR, les valeurs de TPR, et les seuils correspondants. Le premier seuil est fixé à l’infini (tout est prédit négatif), ce qui donne le point (0, 0).

Méthode moderne avec RocCurveDisplay

Depuis scikit-learn 1.0, la classe RocCurveDisplay simplifie le tracé :

from sklearn.metrics import RocCurveDisplay
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.datasets import load_breast_cancer

# Charger et séparer les données
X, y = load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=42
)

# Entraîner le modèle
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)

# Tracé en une ligne
RocCurveDisplay.from_estimator(model, X_test, y_test)
plt.show()

Comparer plusieurs modèles sur le même graphique

L’un des usages les plus puissants de la courbe ROC est la comparaison visuelle de plusieurs classifieurs :

from sklearn.ensemble import RandomForestClassifier
from sklearn.svm import SVC

fig, ax = plt.subplots(figsize=(8, 6))

# Modèle 1 : Régression logistique
lr = LogisticRegression(max_iter=10000).fit(X_train, y_train)
RocCurveDisplay.from_estimator(lr, X_test, y_test,
    name='Logistic Regression', ax=ax)

# Modèle 2 : Random Forest
rf = RandomForestClassifier(n_estimators=100,
    random_state=42).fit(X_train, y_train)
RocCurveDisplay.from_estimator(rf, X_test, y_test,
    name='Random Forest', ax=ax)

# Modèle 3 : SVM
svm = SVC(probability=True).fit(X_train, y_train)
RocCurveDisplay.from_estimator(svm, X_test, y_test,
    name='SVM', ax=ax)

# Ligne de référence
ax.plot([0, 1], [0, 1], 'k--', label='Aléatoire')
ax.legend(loc='lower right')
ax.set_title('Comparaison des modèles')
plt.tight_layout()
plt.show()

Trouver le seuil optimal sur la courbe ROC

La courbe ROC visualise tous les compromis possibles, mais en production, vous devez choisir un seuil unique. Plusieurs méthodes existent pour déterminer ce seuil optimal.

Indice de Youden (J)

L’indice de Youden maximise la somme de la sensibilité et de la spécificité : J = TPR + (1 - FPR) - 1 = TPR - FPR. Graphiquement, c’est le point de la courbe ROC le plus éloigné de la diagonale. Cette méthode suppose que les faux positifs et les faux négatifs ont un coût égal.

# Trouver le seuil optimal par l'indice de Youden
fpr, tpr, thresholds = roc_curve(y_true, y_scores)
youden_index = tpr - fpr
optimal_idx = np.argmax(youden_index)
optimal_threshold = thresholds[optimal_idx]

print(f"Seuil optimal (Youden) : {optimal_threshold:.3f}")
print(f"TPR au seuil optimal  : {tpr[optimal_idx]:.3f}")
print(f"FPR au seuil optimal  : {fpr[optimal_idx]:.3f}")

Distance au coin (0, 1)

Cette méthode minimise la distance euclidienne entre chaque point de la courbe ROC et le coin supérieur gauche parfait (0, 1) : distance = √((FPR)² + (1 - TPR)²). Le résultat est souvent très proche de celui de Youden, mais pas identique quand la courbe est asymétrique.

# Seuil par distance minimale au coin (0, 1)
distances = np.sqrt(fpr**2 + (1 - tpr)**2)
optimal_idx = np.argmin(distances)
optimal_threshold = thresholds[optimal_idx]

Choix guidé par le métier

Les méthodes automatiques (Youden, distance) donnent un seuil « mathématiquement » optimal en pondérant également les deux types d’erreurs. En pratique, les faux positifs et les faux négatifs ont rarement le même coût :

En détection de cancer, un faux négatif (manquer un cancer) est catastrophique. Vous choisirez un seuil bas (haute sensibilité) en acceptant plus de faux positifs (examens complémentaires inutiles).

En détection de spam, un faux positif (email légitime envoyé dans le spam) est très gênant. Vous choisirez un seuil élevé (haute spécificité) en acceptant de laisser passer quelques spams.

En détection de fraude, le coût dépend du montant des transactions. Un modèle de coûts pondérés est souvent préférable aux méthodes génériques.

Conseil pratique Ne vous contentez jamais d’un seuil de 0,5 par défaut. Tracez la courbe ROC, identifiez la zone de FPR acceptable pour votre métier, et choisissez le seuil correspondant sur la courbe. La différence de performance en production peut être significative.

Courbe ROC vs courbe Precision-Recall

La courbe Precision-Recall (PR) est la principale alternative à la courbe ROC. Le choix entre les deux dépend du contexte.

Critère Courbe ROC Courbe Precision-Recall
Axes TPR vs FPR Précision vs Rappel
Utilise les vrais négatifs ? Oui (dans le FPR) Non
Données équilibrées Excellent choix Fonctionne aussi
Données très déséquilibrées Peut être trop optimiste Plus informative
Baseline aléatoire Diagonale (facile à lire) Ligne horizontale = prévalence positive
Résumé scalaire AUC-ROC AUC-PR (Average Precision)
Domaine principal Médecine, scoring, ML général Recherche d’information, détection d’anomalies

Le point clé : la courbe ROC utilise le FPR, qui inclut les vrais négatifs au dénominateur. Quand les négatifs sont très majoritaires (ratio 99:1), le FPR reste artificiellement bas même avec beaucoup de faux positifs en valeur absolue. La courbe PR, en utilisant la précision (qui met les faux positifs au numérateur), reflète mieux cette réalité.

Règle simple : si votre classe positive représente moins de 5 % du dataset, préférez la courbe PR. Entre 5 % et 50 %, la courbe ROC reste fiable. Au-delà de 50 %, les deux conviennent.

ROC en contexte multiclasse

La courbe ROC est conçue pour la classification binaire, mais deux stratégies permettent de l’étendre au multiclasse :

One-vs-Rest (OvR)

Pour chaque classe, on construit une courbe ROC « cette classe vs toutes les autres ». Si vous avez 3 classes (chat, chien, oiseau), vous obtenez 3 courbes ROC : « chat vs non-chat », « chien vs non-chien », « oiseau vs non-oiseau ». L’AUC globale est la moyenne (macro ou pondérée) des AUC individuelles.

One-vs-One (OvO)

On construit une courbe ROC pour chaque paire de classes. Avec 3 classes, cela donne 3 paires (chat-chien, chat-oiseau, chien-oiseau). L’AUC globale est la moyenne des AUC de toutes les paires. Cette méthode est insensible au déséquilibre entre classes quand on utilise la moyenne macro.

from sklearn.metrics import roc_auc_score
from sklearn.preprocessing import label_binarize

# Binariser les labels pour OvR
y_test_bin = label_binarize(y_test, classes=[0, 1, 2])

# AUC multiclasse
auc_ovr = roc_auc_score(y_test_bin, y_prob,
                         multi_class='ovr', average='macro')
auc_ovo = roc_auc_score(y_test, y_prob,
                         multi_class='ovo', average='macro')

print(f"AUC OvR (macro) : {auc_ovr:.4f}")
print(f"AUC OvO (macro) : {auc_ovo:.4f}")

Applications de la courbe ROC par domaine

Médecine et diagnostic

C’est le domaine historique et toujours le plus actif. La courbe ROC sert à évaluer et comparer les tests diagnostiques : mammographies pour le dépistage du cancer du sein, tests sanguins pour les marqueurs tumoraux, scores cliniques pour prédire le risque cardiovasculaire. Le seuil optimal est choisi en fonction du coût relatif des faux négatifs (maladie manquée) et des faux positifs (examens invasifs inutiles).

Scoring de crédit et finance

Les banques utilisent la courbe ROC (via le coefficient de Gini = 2 × AUC – 1) pour évaluer les modèles de scoring de crédit. La réglementation bancaire (Bâle II/III) impose souvent un suivi régulier de la performance des modèles via l’AUC-ROC.

Sécurité et modération

Les systèmes de modération de contenu, de détection de deepfakes et de détection d’intrusion réseau utilisent la courbe ROC pour calibrer le compromis entre détection et fausses alertes. Un système de sécurité ne peut pas être évalué sur un seul seuil : la courbe ROC montre comment les performances évoluent selon le niveau d’alerte choisi.

Benchmarks de machine learning

Les compétitions Kaggle et les benchmarks académiques utilisent l’AUC-ROC comme métrique de classement pour les problèmes de classification binaire. L’avantage : l’AUC ne dépend pas du seuil, ce qui permet de comparer équitablement des modèles même si les participants utiliseraient des seuils différents.

Limites et pièges de la courbe ROC

Le piège du déséquilibre de classes

Sur un dataset avec 99 % de négatifs, le FPR peut rester très bas (par exemple 0,01) tout en correspondant à un grand nombre de faux positifs en absolu. Si vous avez 10 000 négatifs, un FPR de 0,01 signifie 100 faux positifs, ce qui peut être inacceptable. La courbe ROC masque cette réalité car le FPR est exprimé en proportion, pas en valeur absolue.

L’AUC gomme les nuances

L’AUC est un résumé scalaire de la courbe entière. Deux modèles avec la même AUC peuvent avoir des profils très différents : l’un peut exceller à faible FPR (utile en médecine) et l’autre à FPR élevé (moins utile). Quand les courbes se croisent, utilisez l’AUC partielle sur la zone de FPR qui compte pour votre cas d’usage.

L’interpolation linéaire entre points

La courbe ROC empirique (non lissée) est une fonction en escalier. L’interpolation linéaire entre les points peut surestimer les performances réelles, surtout avec peu de données. Avec un petit échantillon de test (< 100 observations), les intervalles de confiance sur l'AUC sont larges. Utilisez le bootstrap ou la validation croisée pour obtenir des estimations fiables.

ROC ne mesure pas la calibration

La courbe ROC ne dépend que du classement relatif des scores, pas de leur valeur absolue. Un modèle bien classé sur la courbe ROC peut produire des probabilités mal calibrées. Si vos probabilités prédites servent directement de base à des décisions (tarification, allocation de ressources), complétez l’analyse ROC par une vérification de calibration.

Bonnes pratiques pour l’analyse ROC

Toujours tracer la courbe, pas seulement l’AUC : l’AUC est un résumé. La forme de la courbe révèle des informations que le chiffre seul ne capture pas (courbes croisées, plateaux, inflexions).

Inclure la diagonale de référence : toujours afficher la ligne diagonale (classifieur aléatoire) pour donner un repère visuel immédiat.

Calculer des intervalles de confiance : une AUC de 0,82 sans intervalle de confiance est peu informative. Utilisez le bootstrap (1000+ itérations) pour estimer l’incertitude. La méthode de DeLong est aussi largement utilisée pour comparer deux courbes ROC.

Annoter le seuil optimal : marquez le point correspondant au seuil retenu sur la courbe et indiquez les valeurs de TPR/FPR/seuil. C’est l’information la plus actionnable du graphique.

Vérifier sur des données non vues : la courbe ROC sur le jeu d’entraînement sera presque toujours trop optimiste, surtout pour des modèles complexes (Random Forest, XGBoost, réseaux de neurones). Seule la courbe sur le jeu de test ou en validation croisée a de la valeur.

Combiner avec la courbe PR si nécessaire : si votre taux de positifs est inférieur à 5 %, la courbe PR complète utilement la courbe ROC.

Test statistique pour comparer deux courbes ROC Le test de DeLong (1988) permet de tester statistiquement si la différence entre deux AUC est significative, à partir des mêmes données. En Python, le package scipy ne l’implémente pas nativement, mais les bibliothèques pROC (R) et fast-delong (Python) le proposent.

Verdict

La courbe ROC reste l’outil de référence pour évaluer et comparer des classifieurs binaires. Sa force principale : elle montre le compromis complet entre sensibilité et fausses alertes, sans imposer de choix de seuil a priori. Son AUC fournit un résumé scalaire intuitif et largement compris.

Ses limites sont connues : elle peut être trop optimiste sur des données très déséquilibrées et l’AUC globale gomme les nuances des courbes qui se croisent. En pratique, tracez toujours la courbe (pas seulement l’AUC), choisissez le seuil en fonction de votre contexte métier, et complétez par la courbe Precision-Recall si vos données sont fortement déséquilibrées.


Questions fréquentes sur la courbe ROC

Quelle est la différence entre la courbe ROC et l’AUC ?

La courbe ROC est le graphique complet qui trace le TPR en fonction du FPR pour chaque seuil. L’AUC est un nombre unique (entre 0 et 1) qui résume cette courbe en mesurant l’aire en dessous. La courbe contient plus d’information que l’AUC seule : elle montre la forme, les inflexions, les zones de performance. L’AUC est un raccourci pour comparer rapidement des modèles, mais elle peut masquer des différences importantes si les courbes se croisent.

Pourquoi la courbe ROC s’appelle « Receiver Operating Characteristic » ?

Le nom vient de la Seconde Guerre mondiale. L’armée américaine a développé cette méthode pour évaluer la capacité des opérateurs radar (« receivers ») à détecter des avions ennemis parmi le bruit de fond. La « caractéristique de fonctionnement » du récepteur décrivait comment ses performances (détection vs fausse alarme) variaient selon le réglage du seuil de sensibilité. Le terme est resté, même si l’usage s’est étendu bien au-delà du radar.

Comment interpréter une courbe ROC qui passe en dessous de la diagonale ?

Une courbe ROC sous la diagonale signifie que le modèle fait systématiquement pire que le hasard (AUC < 0,5). Il classe les positifs comme négatifs et vice versa. La solution est simple : inversez les prédictions (remplacez les labels 0 par 1 et 1 par 0). Vous obtiendrez immédiatement un modèle avec un AUC supérieur à 0,5 sans aucun réentraînement. Ce cas arrive parfois quand les labels sont inversés dans le dataset ou quand le signe de la variable de score est incorrect.

Quelle est la meilleure méthode pour choisir le seuil optimal ?

Il n’y a pas de méthode universelle. L’indice de Youden (qui maximise TPR – FPR) est le plus utilisé quand les erreurs ont un coût symétrique. La méthode de distance au coin (0, 1) donne des résultats similaires. Mais en pratique, le choix du seuil doit être dicté par les coûts métier des erreurs. Si rater un positif coûte 10 fois plus cher qu’une fausse alerte, il faut intégrer cette asymétrie dans le calcul. Aucune méthode automatique ne remplace la connaissance du domaine.

Peut-on utiliser la courbe ROC pour la régression ?

Non, la courbe ROC est exclusivement conçue pour les problèmes de classification (binaire ou multiclasse adaptée). Pour la régression, les métriques pertinentes sont le MSE, le RMSE, le MAE ou le R². Si vous souhaitez transformer un problème de régression en classification (par exemple, « le prix est-il au-dessus de X ? »), alors vous pouvez utiliser la courbe ROC sur le problème binaire résultant.

Polydesk.ai — Footer