Plus facile à lire avec un fond crème, une teinte, plus de contraste ou un texte plus grand ? Choisissez vos couleurs et votre texte, une fois pour toutes les pages.

Leçon gratuite

Juger un classeur honnêtement

Après cette leçon: Je peux juger un classeur avec une matrice de confusion, la précision et le rappel, et pas seulement avec l’exactitude.

Leçon de 60 min2 commandesLab JupyterLab de science des données : pandas, Matplotlib et scikit-learn dans le navigateur

Quatre-vingt-seize pour cent, et inutile

Un filtre à spam est testé sur 1000 messages. Il a juste 960 fois, donc il fait 96 pour cent. L’équipe est contente.

Puis quelqu’un découvre que le filtre répond « pas du spam » à tous les messages, sans exception. Quarante messages sur 1000 étaient pourtant du spam. Un seul score a caché toute la faute.

À la fin de cette leçon

Remarque

Je peux juger un classeur avec une matrice de confusion, la précision et le rappel, et pas seulement avec l’exactitude.

Mots clés

MotCe que ça veut dire
Exactitudela part de tous les messages que le modèle a bien classés
Déséquilibréune étiquette est bien plus fréquente que l’autre
Matrice de confusionun tableau des bonnes et des mauvaises réponses pour chaque étiquette
Précisionparmi les messages signalés, la part qui était vraiment du spam
Rappelparmi les vrais spams, la part qui a été signalée
Seuille score à partir duquel un message est signalé

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

L’exactitude : un nombre pour deux erreurs

L’exactitude compte toutes les bonnes réponses de la même façon. Cela convient quand les étiquettes sont à peu près aussi fréquentes.

Cela échoue quand le tableau est déséquilibré. Si 40 messages sur 1000 sont du spam, un modèle qui ne dit jamais « spam » a juste 960 fois. Il a juste 96 pour cent du temps et ne trouve aucun spam.

Noter un modèle qui ne dit jamais spam

Commande
docker exec jupyter python3 -c "t=[1]*40+[0]*960; g=[0]*1000; print(sum(a==b for a,b in zip(t,g))/1000)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

Compter les quatre sortes de réponse

Le spam est ce que l’on cherche : appelez-le positif. Chaque message tombe dans l’une de quatre cases.

Attrapé : spam, signalé. Fausse alerte : pas du spam, signalé. Manqué : spam, pas signalé. Rejet juste : pas du spam, pas signalé. Les quatre comptes forment la matrice de confusion.

Exemple travaillé : un filtre sur 1000 messages

Signalés comme spamPas signalés
Vraiment du spam (40)Attrapés : 30Manqués : 10
Pas du spam (960)Fausses alertes : 20Rejets justes : 940

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Afficher la matrice, la précision et le rappel

Commande
docker exec jupyter python3 -c "from sklearn.metrics import confusion_matrix, precision_score, recall_score; t=[1]*40+[0]*960; g=[1]*30+[0]*10+[1]*20+[0]*940; print(confusion_matrix(t,g)); print(round(precision_score(t,g),3), round(recall_score(t,g),3), (30+940)/1000)"

Affichée ici, non exécutée. Créez un compte gratuit pour appuyer sur Exécuter et la saisir dans le terminal de votre propre labo.

La précision et le rappel posent deux questions

La précision demande : quand le filtre dit spam, a-t-il souvent raison ? Ici, 30 messages sur les 50 signalés, soit 0.6.

Le rappel demande : parmi les vrais spams, combien le filtre en a-t-il trouvé ? Ici, 30 sur 40, soit 0.75. L’exactitude était de 0.97. Le filtre vaut mieux que celui qui ne dit jamais spam, mais l’exactitude montre à peine de combien.

Bouger le seuil échange l’un contre l’autre

La plupart des modèles donnent un score, et un seuil le transforme en étiquette. Baissez le seuil et plus de messages sont signalés. On attrape plus de spam, mais on signale aussi plus de bons messages.

La précision et le rappel tirent donc en sens contraire, et une personne doit choisir. Lancez le code et regardez bouger les comptes.

Quatre seuils sur dix messages

Code: python
# Dix messages : le score donné par un modèle (de 0 à 1) et le message était-il du spam.
messages = [
    (0.95, 1), (0.9, 1), (0.8, 0), (0.7, 1), (0.6, 0),
    (0.5, 1), (0.4, 0), (0.3, 0), (0.2, 0), (0.1, 0),
]
for seuil in [0.9, 0.7, 0.5, 0.3]:
    attrapes = 0
    fausses_alertes = 0
    manques = 0
    for score, spam in messages:
        signale = score >= seuil
        if signale and spam == 1:
            attrapes = attrapes + 1
        if signale and spam == 0:
            fausses_alertes = fausses_alertes + 1
        if not signale and spam == 1:
            manques = manques + 1
    print("seuil", seuil, "attrapés", attrapes, "fausses alertes", fausses_alertes, "manqués", manques)
# Quel seuil choisiriez-vous pour une boîte mail ? Et pour une banque ?

Exemple travaillé : ce que donne chaque seuil

SeuilAttrapésFausses alertesManquésPrécisionRappel
0.92021.00.5
0.73110.750.75
0.54200.6671.0
0.34400.51.0

Les cellules que les étudiants remplissent restent vides dans cet aperçu.

Une erreur fréquente

Attention

Beaucoup pensent qu’il existe un meilleur seuil, le même pour tous. Il n’y en a pas tant que l’on ne connaît pas le coût de chaque erreur. Une boîte mail peut vivre avec un peu de spam. Un contrôle de fraude ne peut pas en laisser passer.

Plus loin : le coût de chaque erreur

Admettons qu’un spam manqué coûte 1 minute de lecture et qu’une fausse alerte coûte 5 minutes de recherche d’un message perdu. Reprenez le tableau des quatre seuils.

Calculez les minutes perdues à chaque seuil. Quel seuil coûte le moins ? Cela changerait-il si une fausse alerte ne coûtait qu’1 minute ?

À propos de ce labo et de sa source: Lab JupyterLab de science des données : pandas, Matplotlib et scikit-learn dans le navigateur

Vous enseignez à une classe ? Proposez ce module à vos étudiants avec un guide de l'enseignant, des devoirs corrigés et un laboratoire pour chaque étudiant.