Métriques de classification : au-delà de l'accuracy

Première leçon du cours Évaluation et validation des modèles, en accès libre : environ 15 minutes, 3 exercices et 3 questions de quiz. C'est la leçon de base du catalogue ; dans l'espace étudiant, elle est réécrite pour ton profil.

Objectifs

  • Lire une matrice de confusion
  • Calculer précision, rappel et F1 et savoir lequel privilégier
  • Reconnaître le piège de l'accuracy sur des classes déséquilibrées

Matrice de confusionPrécision et rappelScore F1

L’accuracy (proportion de bonnes prédictions) est intuitive, mais elle peut être trompeuse. Prenons un problème de détection de fraude avec 10 % de cas positifs :

from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.dummy import DummyClassifier

X, y = make_classification(n_samples=3000, n_features=12, n_informative=6, weights=[0.9],
                           class_sep=1.5, random_state=0)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, stratify=y, random_state=0)

naif = DummyClassifier(strategy="most_frequent").fit(X_train, y_train)
print(naif.score(X_test, y_test))   # environ 0.90 sans rien apprendre !

Un modèle qui répond toujours « pas de fraude » obtient 90 % d’accuracy… et ne détecte aucune fraude. Il faut des métriques qui regardent chaque type d’erreur.

La matrice de confusion

from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import confusion_matrix

clf = make_pipeline(StandardScaler(), LogisticRegression()).fit(X_train, y_train)
y_pred = clf.predict(X_test)
print(confusion_matrix(y_test, y_pred))
# [[663   9]     lignes = classes réelles, colonnes = classes prédites
#  [ 28  50]]

En binaire, avec la classe positive 1 :

prédit 0 prédit 1
réel 0 VN : vrais négatifs (663) FP : faux positifs (9)
réel 1 FN : faux négatifs (28) VP : vrais positifs (50)

ConfusionMatrixDisplay.from_estimator(clf, X_test, y_test) en donne une version graphique.

Précision, rappel, F1

  • Précision = VP / (VP + FP) = 50 / 59 ≈ 0,85 : quand le modèle lance une alerte, il a raison 85 % du temps.
  • Rappel (sensibilité) = VP / (VP + FN) = 50 / 78 ≈ 0,64 : le modèle détecte 64 % des fraudes.
  • F1 = 2 × précision × rappel / (précision + rappel) ≈ 0,73 : la moyenne harmonique, élevée seulement si les deux le sont.
from sklearn.metrics import precision_score, recall_score, f1_score, classification_report

print(precision_score(y_test, y_pred), recall_score(y_test, y_pred), f1_score(y_test, y_pred))
print(classification_report(y_test, y_pred, digits=3))

classification_report affiche ces métriques pour chaque classe, ainsi que les moyennes macro (moyenne simple des classes, qui donne autant de poids à la classe rare) et weighted (pondérée par l’effectif). La balanced accuracy (balanced_accuracy_score), moyenne des rappels de chaque classe, vaut 0,5 pour le modèle naïf : elle ne se laisse pas tromper par le déséquilibre.

Quelle métrique choisir ?

Tout dépend du coût des erreurs :

  • Dépistage médical, fraude : un faux négatif coûte cher → privilégier le rappel (tout en surveillant la précision).
  • Filtre anti-spam, recommandation : un faux positif agace l’utilisateur → privilégier la précision.
  • Compromis équilibré : le F1.
  • Classes équilibrées et erreurs de coût similaire : l’accuracy reste acceptable.

Pour les problèmes multiclasses, precision_score(..., average="macro") ou "weighted" résume les classes en un nombre. Fixez la métrique avant de comparer des modèles, en accord avec les équipes métier : changer de métrique après coup pour flatter un modèle est une forme de biais.

Notez enfin que ces métriques dépendent du seuil de décision (0,5 par défaut). La leçon suivante montre comment les évaluer indépendamment du seuil, puis comment le choisir.

Exercices

Les solutions et les tests restent sur le serveur. Dans l'espace étudiant, ton code est exécuté et corrigé, et le tuteur donne des indices avant la solution.

  1. CodeDifficulté 1Python dans le navigateur1 indice

    Démasquer le modèle naïf

    Entraînez un DummyClassifier(strategy='most_frequent'). Stockez son accuracy de test dans acc_naif et son rappel sur la classe 1 dans rappel_naif (utilisez recall_score).

    from sklearn.datasets import make_classification
    from sklearn.model_selection import train_test_split
    
    X, y = make_classification(n_samples=3000, n_features=12, n_informative=6, weights=[0.9],
                               class_sep=1.5, random_state=0)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, stratify=y, random_state=0)
    from sklearn.dummy import DummyClassifier
    from sklearn.metrics import recall_score
    
    acc_naif = ...
    rappel_naif = ...
  2. CodeDifficulté 2Python dans le navigateur1 indice

    Matrice de confusion et métriques

    Entraînez clf (pipeline StandardScaler + LogisticRegression()), prédisez le test, puis extrayez vn, fp, fn, vp de la matrice de confusion. Calculez à la main precision = vp / (vp + fp) et rappel = vp / (vp + fn), et stockez le F1 calculé avec f1_score dans f1.

    from sklearn.datasets import make_classification
    from sklearn.model_selection import train_test_split
    
    X, y = make_classification(n_samples=3000, n_features=12, n_informative=6, weights=[0.9],
                               class_sep=1.5, random_state=0)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, stratify=y, random_state=0)
    from sklearn.pipeline import make_pipeline
    from sklearn.preprocessing import StandardScaler
    from sklearn.linear_model import LogisticRegression
    from sklearn.metrics import confusion_matrix, f1_score
    
    clf = ...
    # vn, fp, fn, vp = ...
    precision = ...
    rappel = ...
    f1 = ...
  3. QCMDifficulté 21 indice

    Choisir la métrique

    Une banque veut détecter le maximum de transactions frauduleuses, quitte à vérifier quelques transactions légitimes. Quelle métrique privilégier ?

    • La précision
    • Le rappel
    • L'accuracy
    • Le R²

Quiz de fin de leçon

  1. Dans confusion_matrix de scikit-learn, que représentent les lignes ?

    • Les classes prédites
    • Les classes réelles
    • Les seuils
    • Les features
  2. Le rappel mesure :

    • La part des alertes qui sont justes
    • La part des vrais positifs détectés
    • La part de bonnes prédictions
    • L'aire sous la courbe ROC
  3. Que vaut la balanced accuracy d’un modèle qui prédit toujours la classe majoritaire en binaire ?

    • 0
    • 0.5
    • L'accuracy
    • 1

La suite du cours

  1. Courbes ROC et précision-rappel, choix du seuil15 min
  2. Stratégies de validation croisée15 min
  3. Recherche d'hyperparamètres : GridSearchCV et RandomizedSearchCV20 min
  4. Diagnostiquer un modèle : courbes et fuites de données20 min

Évaluation et validation des modèles · Intermédiaire · 2 h 55