Seuils et calibration
- Leçon 20
- 75 min
- Module 6 : Régler et finaliser le modèle
Leçon 20 sur 27 · Apprentissage automatique : du problème à un modèle fiableSeuils et calibration
1. Comprendre l'apprentissage automatique
2. Cadrer le problème de prédiction
3. Évaluer les modèles supervisés
4. Créer les premiers modèles
5. Essayer d'autres familles de modèles
6. Régler et finaliser le modèle
7. Comprendre et choisir le modèle
8. Préparer la passation du modèle
Ce que vous saurez faire
Transformez les scores du modèle en signalements que l’équipe senior peut traiter. Vérifiez si les gens peuvent lire un score comme une probabilité. Faites ensuite passer au modèle son unique examen final sur les données de test. Le seuil par défaut ne signale presque rien. Un score juste l’an dernier peut être trop bas maintenant. Aucun de ces problèmes ne déclenche d’erreur.
Carnet JupyterFaites cette leçon dans un carnet Jupyter
Le carnet (notebook) Jupyter contient toutes les cellules de code, les tâches et les vérifications de cette leçon. Il contient aussi l’exercice du module et sa vérification, avec les consignes. Ses cellules de préparation installent pandas et scikit-learn. Elles téléchargent les données d’exercice, ticket_model.py et train.py. Vous écrivez evaluate.py dans le carnet. Il fonctionne donc sans le projet local. Utilisez l’explorateur et le graphique ici, et exécutez le code dans le carnet.
Le carnet est en anglais. Colab et Kaggle ouvrent votre propre copie. Il faut un compte Google ou Kaggle gratuit. Vous êtes bloqué ? Consultez le carnet de solution.
Avant de commencerCe qu’il faut savoir et avoir sous la main
Ce que vous devez savoir
- La matrice de confusion, la précision et le rappel, dans Les métriques de classification : la matrice de confusion et La précision et le rappel.
- Comment un seuil échange de la précision contre du rappel, dans Le compromis entre précision et rappel. Cette leçon l’applique au modèle entraîné.
- Pourquoi utiliser les données de test une seule fois, à la fin, dans Données d’entraînement, de validation et de test : trois jeux de données, trois rôles.
- Le modèle choisi et la règle d’une erreur-type, dans Régler les hyperparamètres : la règle d’une erreur-type.
predictetpredict_proba, dans Comprendre la classification.- La calibration et son diagramme, dans Calibration et sous-groupes, et la courbe des coûts, dans Seuils et coûts. Ces deux leçons font partie de Mathématiques et statistiques essentielles pour l’IA.
Ce qu’il vous faut sur votre ordinateur (seulement pour le parcours local; le carnet n’en a pas besoin)
- Le dossier du projet
~/projects/ticket-model, avec son environnement.venvactif et les données dansdata/. Voir Définir une référence de base : préparer votre projet. Si un fichier de données manque ou a changé, exécutezpython get_data.py --reset. ticket_model.pyavec 11 caractéristiques, dans Sélectionner les caractéristiques utiles : modifier ticket_model.py.experiment_log.csvavec les lignes E01 à E21, dans Régler les hyperparamètres : consigner dans le journal des expériences. Cette leçon le lit sans ajouter de ligne.- Cette leçon ajoute
train.py(téléchargé),evaluate.py(que vous écrivez), et les dossiersmodel/etreports/. Voir Tester une seule fois avec evaluate.py. - Si un fichier manque ou ne fonctionne plus, suivez Revenir à un état connu à la fin de cette leçon.
Testé sur macOS avec Python 3.14.6, pandas 3.0.6, scikit-learn 1.9.1, joblib 1.6.0 et matplotlib 3.11.2. Les commandes Windows n’ont pas été testées. Le carnet a été testé dans Jupyter.
Du score au signalement
Section intitulée « Du score au signalement »Une petite clinique a un médecin disponible cet après-midi, avec du temps pour trois patients. Dix personnes attendent. Une infirmière examine chaque personne et note un score d’urgence. Le médecin voit ensuite les trois personnes aux scores les plus élevés. L’infirmière n’a pas besoin d’un seuil « correct » : le temps du médecin le détermine. Avec du temps pour trois personnes, le seuil correspond au score de la troisième personne la plus urgente.
L’équipe senior de Grace fonctionne de la même façon. Vous connaissez déjà les outils présentés dans Le compromis entre précision et rappel. Un score classe les billets de soutien. Un seuil transforme le score en signalement : signalez le billet si son score atteint ou dépasse le seuil. Un seuil plus bas augmente le rappel et diminue la précision. L’équipe de Grace peut examiner au plus 20 % des billets. Cette limite est sa capacité. Dans cette leçon, vous avez choisi le seuil de points le plus bas qui respecte cette limite : 3 points ou plus.
Une chose est nouvelle dans cette leçon : le score vient maintenant du modèle entraîné. C’est un nombre entre 0 et 1 qui peut prendre de nombreuses valeurs. Le seuil peut donc varier par petits pas, sans règle pour départager les égalités. La règle reste la même : le meilleur seuil est le plus bas qui respecte la capacité. Il détecte le plus de cas transférés à l’équipe senior que celle-ci peut examiner. Voici dix scores, avec une capacité de 3 billets sur 10 (30 %) :
| Seuil | Scores qui atteignent ou dépassent le seuil | Signalés | Respecte les 30 %? |
|---|---|---|---|
| 0,43 | 0,81, 0,62, 0,55, 0,43 | 4 (40 %) | Non |
| 0,44 | 0,81, 0,62, 0,55 | 3 (30 %) | Oui : le plus bas qui convient |
| 0,56 | 0,81, 0,62 | 2 (20 %) | Oui, mais il manque le billet à 0,55 |
choose_threshold() procède par pas de 0,01. Cette fonction se trouve dans le fichier train.py du cours, que vous téléchargerez plus loin dans cette leçon :
def choose_threshold(scores, capacity): """The lowest threshold (in steps of 0.01) that flags no more than `capacity` of the tickets. Lower thresholds flag more tickets and catch more escalations, so the lowest one that fits catches the most.""" for step in range(1, 100): threshold = step / 100 if (scores >= threshold).mean() <= capacity: return threshold return 1.0Comme dans chaque carnet de ce cours, np désigne NumPy et pd désigne pandas. Les cellules de préparation du carnet les importent.
scores_10 = np.array([0.81, 0.62, 0.55, 0.43, 0.38, 0.30, 0.22, 0.15, 0.09, 0.04])threshold_10 = choose_threshold(scores_10, 0.3)print("threshold:", threshold_10, "| flagged:", (scores_10 >= threshold_10).sum())threshold: 0.44 | flagged: 3Exemple détaillé : le seuil sur les données de validation
Section intitulée « Exemple détaillé : le seuil sur les données de validation »Le seuil est un choix. On le choisit donc sur les données de validation, jamais sur les données de test. Priya entraîne le modèle final sur les données d’entraînement. Elle calcule les scores des 1 179 billets de mai et affiche les quatre comptes pour six seuils :
from sklearn.metrics import confusion_matrixfrom ticket_model import FEATURES, TARGET, build_pipeline, load
train, valid = load("train"), load("valid")pipeline = build_pipeline().fit(train[FEATURES], train[TARGET])scores = pipeline.predict_proba(valid[FEATURES])[:, 1]for threshold in [0.5, 0.3, 0.2, 0.19, 0.15, 0.1]: flags = (scores >= threshold).astype(int) tn, fp, fn, tp = confusion_matrix(valid[TARGET], flags).ravel() print(f"{threshold:4}: flagged {tp + fp:3d} ({(tp + fp) / len(valid):5.1%}) TP {tp:3d} FP {fp:3d} FN {fn:3d} TN {tn:3d}" f" precision {tp / (tp + fp):.3f} recall {tp / (tp + fn):.3f}") 0.5: flagged 25 ( 2.1%) TP 17 FP 8 FN 166 TN 988 precision 0.680 recall 0.093 0.3: flagged 92 ( 7.8%) TP 46 FP 46 FN 137 TN 950 precision 0.500 recall 0.251 0.2: flagged 203 (17.2%) TP 81 FP 122 FN 102 TN 874 precision 0.399 recall 0.4430.19: flagged 227 (19.3%) TP 86 FP 141 FN 97 TN 855 precision 0.379 recall 0.4700.15: flagged 314 (26.6%) TP 106 FP 208 FN 77 TN 788 precision 0.338 recall 0.579 0.1: flagged 475 (40.3%) TP 128 FP 347 FN 55 TN 649 precision 0.269 recall 0.699C’est le compromis du module 3, cette fois avec le vrai modèle. Chaque baisse détecte plus de cas transférés et entraîne plus d’examens inutiles. Les données ne peuvent pas décider quel seuil convient. Grace donne la réponse : au plus 20 % des billets.
threshold = choose_threshold(scores, 0.20)flags = (scores >= threshold).astype(int)print("threshold:", threshold, f"| flagged {flags.sum()} of {len(valid)} ({flags.mean():.1%})")threshold: 0.19 | flagged 227 of 1179 (19.3%)Le seuil est de 0,19. À 0,18, le modèle signale 248 billets (21,0 %), ce qui dépasse la capacité. À 0,19, il détecte 86 des 183 cas transférés (rappel de 0,470), avec 227 examens. La règle de priorité 1 en détecte 61 avec 163 examens (rappel de 0,333). L’objectif d’amélioration de Définir une référence de base est donc atteint sur les données de validation. Il exige au plus 20 % de billets signalés et au moins 40 % des cas transférés détectés.
Trois matrices de confusion
Section intitulée « Trois matrices de confusion »Chaque colonne représente la matrice de confusion du même modèle sur les mêmes 1 179 billets de mai, à un seuil. Seul le seuil change :
| Seuil de 0,5 (par défaut) | Seuil de 0,19 (choisi) | Seuil de 0,1 | |
|---|---|---|---|
| Détectés : transférés, signalés (VP) | 17 | 86 | 128 |
| Manqués : transférés, non signalés (FN) | 166 | 97 | 55 |
| Fausses alertes : non transférés, signalés (FP) | 8 | 141 | 347 |
| Correctement laissés : non transférés, non signalés (VN) | 988 | 855 | 649 |
| Signalés | 25 (2,1 %) | 227 (19,3 %) | 475 (40,3 %) |
| Précision | 0,680 | 0,379 | 0,269 |
| Rappel | 0,093 | 0,470 | 0,699 |
- À 0,5, l’équipe reçoit 25 examens dans le mois, et 166 cas transférés attendent dans la file normale. La précision est élevée parce que seuls les cas les plus évidents passent.
- À 0,1, l’équipe reçoit 475 examens, soit deux fois sa capacité. Parmi eux, 347 sont inutiles, soit presque trois sur quatre.
- À 0,19, l’équipe atteint sa capacité et détecte presque la moitié des cas transférés. Environ 4 examens sur 10 trouvent un cas transféré, et un examen prend environ 10 minutes.
Explorer le seuil sur les vrais scores
Section intitulée « Explorer le seuil sur les vrais scores »L’explorateur contient les scores du modèle final pour les 1 179 billets de mai. Il y a 996 billets non transférés (panneau supérieur) et 183 billets transférés (panneau inférieur). Ce sont les mêmes scores que dans le tableau, donc tous les comptes correspondent.
Explorer
Le seuil adapté à la capacité de l'équipe senior
Prédisez d’abord : La capacité est de 20 % des billets : au plus 235 de ces 1 179 billets. Quel est le seuil le plus bas qui convient? Combien des 183 cas transférés détecte-t-il?
Les barres pleines sont signalées (score égal ou supérieur au seuil). Les barres pâles ne sont pas signalées. Vous pouvez aussi faire glisser la poignée ronde sur la ligne, ou la sélectionner et appuyer sur les flèches (Maj pour des pas de 0,10). Les vérifications par semaine supposent 266 billets par semaine, avec la même répartition que ces 1 179.
Au seuil 0,50, le modèle en signale 25 : 17 de la classe « transférés » et 8 fausses alertes. Il manque 166 des 183 billets de la classe « transférés ».
| Classe réelle | Signalés | Non signalés | Total |
|---|---|---|---|
| Transférés | 17vrai positif | 166faux négatif (manqué) | 183 |
| Non transférés | 8faux positif (fausse alerte) | 988vrai négatif | 996 |
| Total | 25 | 1 154 | 1 179 |
- Signalés
- 25
- sur 1 179 billets
- Précision
- 68,0 %
- 17 sur 25 signalés
- Rappel
- 9,3 %
- 17 sur 183
- Taux de faux positifs
- 0,8 %
- 8 sur 996
- Vérifications par semaine
- 6
- environ 1 par jour
Description textuelle de l’explorateur
Le panneau supérieur est un histogramme des scores des 996 billets non transférés. La plupart des scores sont bas : deux sur trois sont sous 0,10. La barre la plus haute couvre 0,02 à 0,04 (225 billets), et la médiane est de 0,065. Le score le plus élevé est de 0,91. Le panneau inférieur est un histogramme des 183 billets transférés. Leurs scores sont plus dispersés, de 0,02 à 0,80, avec une médiane de 0,18. Environ 3 billets transférés sur 10 ont un score inférieur à 0,10. Aucun seuil ne peut donc les détecter sans signaler la plupart des billets. Les deux panneaux se chevauchent sur la majeure partie de l’étendue. Une ligne verticale indique le seuil.
Au seuil initial de 0,50, le modèle signale 25 billets : 17 transférés et 8 non transférés. Il manque 166 cas transférés. La précision est de 68,0 %, le rappel de 9,3 %, et l’équipe reçoit environ 6 examens par semaine. À 0,30 : 92 signalés, rappel de 25,1 %. À 0,19 : 227 signalés (86 transférés, 141 non transférés), 97 manqués, précision de 37,9 %, rappel de 47,0 %. Cela donne environ 51 examens par semaine, soit environ 7 par jour. À 0,18, 248 billets sont signalés, ce qui dépasse 235. À 0,10 : 475 signalés, rappel de 69,9 %, environ 107 examens par semaine.
Abaissez le seuil de 0,50 à 0,19 et observez les examens par semaine. L’explorateur suppose 266 billets par semaine (1 179 billets de mai ÷ 31 jours × 7). La capacité de 20 % correspond à environ 53 examens par semaine. À 0,19, l’équipe en reçoit environ 51; à 0,18, environ 56, ce qui est trop.
Calibration : peut-on lire un score comme une probabilité?
Section intitulée « Calibration : peut-on lire un score comme une probabilité? »Une météorologue annonce « 70 % de probabilité de pluie ». Comment savoir si ses prévisions sont bonnes? Rassemblez tous les jours où elle a annoncé 70 %. S’il a plu environ 7 de ces jours sur 10, son 70 % correspond à la réalité. S’il n’a plu que 4 jours sur 10, ses chiffres sont trop élevés. C’est vrai même si elle classe correctement les jours pluvieux devant les jours secs.
Grace a un projet semblable. Elle veut afficher « probabilité de transfert : 24 % » près d’un billet, pour chaque agent. Ce n’est honnête que si environ 24 % des billets au score proche de 0,24 sont réellement transférés. Un modèle qui a cette propriété est calibré : ses scores correspondent à la fréquence des événements. Dans Calibration et sous-groupes, dans le cours de mathématiques, vous avez lu un diagramme de calibration. Maintenant, vous vérifiez un vrai modèle, sur les données d’entraînement et sur le mois suivant le changement de politique.
Un nombre résume cela : le score de Brier, la moyenne de (score − résultat)². Le résultat vaut 1 pour un transfert et 0 sinon. Plus le score est bas, mieux c’est. Voici quatre billets :
| Billet | Score | Transféré | (score − résultat)² |
|---|---|---|---|
| A | 0,9 | 1 | (0,9 − 1)² = 0,01 |
| B | 0,2 | 0 | 0,04 |
| C | 0,6 | 0 | 0,36 |
| D | 0,1 | 0 | 0,01 |
Score de Brier = (0,01 + 0,04 + 0,36 + 0,01) ÷ 4 = 0,105. Le billet C contribue le plus : un score confiant, mais faux. Le score de Brier mélange deux choses : la qualité du classement des billets et la correspondance entre scores et taux. Pour voir uniquement la calibration, il faut donc aussi le graphique ci-dessous.
Pour le vrai modèle, Priya regroupe les scores par intervalles. Elle compare le score moyen au taux de transfert observé dans chaque intervalle :
train_scores = pipeline.predict_proba(train[FEATURES])[:, 1]bins = [0, 0.05, 0.1, 0.2, 0.3, 0.5, 1]
def reliability(part, part_scores): """Tickets, mean score and observed escalation rate per score bin.""" table = pd.DataFrame({"score": part_scores, "escalated": part[TARGET].to_numpy()}) return table.groupby(pd.cut(part_scores, bins), observed=True).agg( tickets=("escalated", "size"), mean_score=("score", "mean"), rate=("escalated", "mean")).round(3)
print("train\n", reliability(train, train_scores))print("valid\n", reliability(valid, scores))train tickets mean_score rate(0.0, 0.05] 5576 0.031 0.030(0.05, 0.1] 4713 0.072 0.072(0.1, 0.2] 3843 0.142 0.140(0.2, 0.3] 1493 0.244 0.249(0.3, 0.5] 1025 0.376 0.389(0.5, 1.0] 289 0.614 0.574valid tickets mean_score rate(0.0, 0.05] 414 0.031 0.053(0.05, 0.1] 290 0.071 0.114(0.1, 0.2] 272 0.145 0.173(0.2, 0.3] 111 0.241 0.315(0.3, 0.5] 67 0.388 0.433(0.5, 1.0] 25 0.625 0.680Sur les données d’entraînement, le score moyen de chaque intervalle est proche de son taux. Les scores de 0,2 à 0,3 ont une moyenne de 0,244, et 24,9 % de ces billets ont été transférés. En mai, tous les taux dépassent le score moyen. Le même intervalle a une moyenne de 0,241, et 31,5 % des billets ont été transférés.
Le graphique de fiabilité
Section intitulée « Le graphique de fiabilité »Un graphique de fiabilité est le diagramme de calibration que vous avez lu dans le cours de mathématiques. Il représente les mêmes intervalles : un point par intervalle, placé selon son score moyen et son taux observé. Un point sur la diagonale en pointillés signifie « score = taux ». C’est comme une météorologue dont les jours annoncés à 70 % sont pluvieux 7 fois sur 10.
- Entraînement (juillet 2024 à avril 2026)
- Validation (mai 2026)
- Calibration parfaite (pointillés)
Description textuelle du graphique
Un graphique carré. L’axe horizontal représente le score moyen d’un intervalle, et l’axe vertical, le taux de transfert observé. Les deux vont de 0 à 0,7. Une diagonale en pointillés indique une calibration parfaite. La courbe d’entraînement compte six points, tous proches de la diagonale : (0,031, 0,030), (0,072, 0,072), (0,142, 0,140), (0,244, 0,249), (0,376, 0,389) et (0,614, 0,574). Seul le dernier intervalle, avec 289 billets, est légèrement en dessous. La courbe de validation compte six points, tous au-dessus de la diagonale : (0,031, 0,053), (0,071, 0,114), (0,145, 0,173), (0,241, 0,315), (0,388, 0,433) et (0,625, 0,680). Un point marqué indique l’intervalle de 0,2 à 0,3 en mai : score moyen de 0,24, taux de 31,5 %. Le dernier intervalle de validation ne compte que 25 billets.
Le modèle est calibré sur les mois dont il a appris, et il sous-estime le risque en mai. Le score de Brier montre la même chose :
from sklearn.metrics import brier_score_loss
print(f"train: model {brier_score_loss(train[TARGET], train_scores):.4f}, constant 0.117 {brier_score_loss(train[TARGET], np.full(len(train), 0.117)):.4f}")print(f"valid: model {brier_score_loss(valid[TARGET], scores):.4f}, constant 0.117 {brier_score_loss(valid[TARGET], np.full(len(valid), 0.117)):.4f}")print(f"valid: mean score {scores.mean():.3f}, escalation rate {valid[TARGET].mean():.3f}")train: model 0.0902, constant 0.117 0.1034valid: model 0.1155, constant 0.117 0.1326valid: mean score 0.120, escalation rate 0.155Le modèle fait mieux qu’un score constant de 0,117 sur les deux jeux de données. Son score de Brier est moins bon sur les données de validation (0,1155 contre 0,0902). C’est en partie attendu : avec plus de transferts, tous les modèles ont un score de Brier plus élevé. Le reste vient de l’écart : le modèle annonce 12,0 % en moyenne, et 15,5 % des billets sont transférés.
Que faire de cet écart
Section intitulée « Que faire de cet écart »Trouvez d’abord où se situe l’écart. Le changement de politique concernait les garanties, donc Priya compare les équipes :
by_team = valid.assign(score=scores).groupby("team").agg( tickets=(TARGET, "size"), mean_score=("score", "mean"), rate=(TARGET, "mean"))print(by_team.round(3)) tickets mean_score rateteamaccount 166 0.057 0.072delivery 348 0.092 0.121payment 206 0.214 0.233returns 291 0.098 0.113warranty 168 0.163 0.286Les billets de garantie ont le plus grand écart : score moyen de 0,163 et taux de 0,286. Cela représente environ 12 points de pourcentage. Le modèle a appris le taux des garanties avant le changement de politique.
Demandez ensuite ce que l’écart compromet. La règle de capacité utilise seulement l’ordre des scores. Elle signale les billets les plus risqués jusqu’à atteindre la capacité, comme la liste de l’infirmière. Si tous les scores sont trop bas du même montant, l’ordre reste le même. Priya le vérifie : elle ajoute 0,035 à chaque score. La moyenne passe ainsi de 0,120 au taux réel.
from sklearn.metrics import average_precision_score
shifted = np.clip(scores + 0.035, 0, 1)print(f"mean score: {scores.mean():.3f} -> {shifted.mean():.3f}")print("average precision:", round(average_precision_score(valid[TARGET], scores), 3), "->", round(average_precision_score(valid[TARGET], shifted), 3))mean score: 0.120 -> 0.155average precision: 0.391 -> 0.391L’ordre n’a pas changé, donc la précision moyenne n’a pas changé. Cela mène à trois conclusions :
- Le seuil de 0,19 fonctionne toujours. Il signale les 19,3 % des billets de mai les plus risqués. Ce classement reste valable après le changement de politique.
- Il ne faut pas présenter les scores comme « la probabilité de transfert ». Un billet de garantie au score de 0,16 est transféré presque deux fois plus souvent que 16 %. Un tableau de bord affichant « 16 % » induirait les agents de Grace en erreur.
- La solution demande de nouvelles données, pas un nouveau seuil. Une méthode consiste à recalibrer les scores sur des billets récents étiquetés. Cela signifie apprendre une correspondance entre score et taux observé, par exemple avec
CalibratedClassifierCVde scikit-learn. Vérifiez-la ensuite sur un mois ultérieur. L’autre méthode consiste à réentraîner le modèle en incluant mai et juin. Le module 8 en fait le plan de réentraînement.
Exercice guidé : choisir et vérifier le seuil
Section intitulée « Exercice guidé : choisir et vérifier le seuil »Utilisez les sections 1 à 4 du carnet.
- Exécutez les cellules de préparation. Vous devriez voir la ligne
Ready:(prêt). - Exécutez la section 1. Vous devriez voir
threshold: 0.44 | flagged: 3(seuil : 0,44; signalés : 3). - Exécutez le tableau des seuils dans la section 2. Vérifiez la ligne de 0,19 : 227 signalés, rappel de 0,470.
- Prédisez le seuil pour une capacité de 20 %, puis exécutez la cellule suivante. Vous devriez voir
threshold: 0.19(seuil : 0,19). - Dans la section 4, exécutez le tableau de fiabilité et le graphique. La courbe de validation doit être au-dessus de la diagonale.
- Calculez
brier_validà la main : la moyenne de (score − résultat)², arrondie à 4 décimales. - Exécutez la cellule de vérification. Elle affiche
Check passed: brier_valid is right.(vérification réussie : brier_valid est correct) si votre valeur est correcte. - Exécutez la cellule
brier_score_loss. Votre valeur doit être égale à celle de la ligne de validation.
Afficher la réponse
brier_valid = round(float(np.mean((scores - valid[TARGET].to_numpy()) ** 2)), 4)print(brier_valid)0.1155Elle est égale à brier_score_loss sur les données de validation : 0,1155.
À vous de jouer : une semaine chargée à 15 %
Section intitulée « À vous de jouer : une semaine chargée à 15 % »Changez une condition. Grace dit que, pendant une semaine chargée, son équipe peut examiner seulement 15 % des billets. Avant l’exécution, faites une prédiction : le seuil monte-t-il ou descend-il? Le rappel monte-t-il ou descend-il? Calculez ensuite le seuil avec choose_threshold(scores, 0.15) et comptez les billets de mai signalés (carnet, section 2).
Afficher la réponse
threshold_15 = choose_threshold(scores, 0.15)flagged_15 = int((scores >= threshold_15).sum())print(threshold_15, flagged_15)0.22 174Le seuil monte à 0,22 : 174 billets signalés (14,8 %). Avec moins d’examens, le rappel descend à 0,410 (75 cas sur 183 détectés). La précision monte à 0,431, car seuls les cas les plus évidents passent. Le modèle détecte encore plus de cas transférés que la règle de priorité 1 (61 transferts). Le nombre d’examens est presque identique (174 contre 163).
Erreur courante
Le seuil par défaut de predict()
Symptôme : Tomás utilise pipeline.predict(), comme dans la plupart des tutoriels :
flags_default = pipeline.predict(valid[FEATURES])print("predict() flags:", flags_default.sum(), f"({flags_default.mean():.1%})")predict() flags: 25 (2.1%)L’équipe expérimentée reçoit 25 billets à examiner en un mois et a du temps libre. Pendant ce temps, 166 des 183 cas transférés attendent dans la file normale. Il n’y a ni erreur ni avertissement.
Cause : predict() utilise un seuil de 0,5. Seulement 25 billets de mai ont un score aussi élevé. En effet, seulement 15,5 % des billets sont transférés, et le modèle est prudent. La valeur 0,5 est un choix par défaut de la bibliothèque, pas une décision de l’entreprise.
Solution : utilisez predict_proba() et choisissez le seuil sur les données de validation selon la décision : choose_threshold(scores, 0.20) donne 0,19. Enregistrez le seuil avec le modèle pour que chaque utilisateur applique le même. train.py l’écrit dans model_info.json.
Conséquence dans le travail en IA : un modèle qui classe bien les cas (aire sous la courbe ROC de 0,752) ne fait presque rien. Il manque un seul nombre. Une équipe qui vérifie seulement que « le modèle est déployé » ne voit jamais ce problème. Vérifiez chaque semaine le taux de signalement par rapport à la capacité (module 8).
Facultatif : une analyse des coûts
Section intitulée « Facultatif : une analyse des coûts »Cette partie est facultative. Voici les coûts approximatifs de Grace : un examen prend environ 10 minutes à un agent expérimenté. Supposons qu’un transfert manqué coûte environ 60 minutes de travail ultérieur (et un client mécontent). Le coût total à un seuil donné est donc 10 × billets signalés + 60 × transferts manqués, en minutes. Seuils et coûts, dans le cours de mathématiques, explique la courbe des coûts.
Explorer
Facultatif : quel serait le seuil le moins coûteux
Prédisez d’abord : Avec un examen de 10 minutes et un transfert manqué de 60 minutes, le seuil le moins coûteux dépasse-t-il 0,19?
Les barres pleines sont signalées (score égal ou supérieur au seuil). Les barres pâles ne sont pas signalées. Vous pouvez aussi faire glisser la poignée ronde sur la ligne, ou la sélectionner et appuyer sur les flèches (Maj pour des pas de 0,10).
Au seuil 0,19, le modèle en signale 227 : 86 de la classe « transféré » et 141 fausses alertes. Il manque 97 des 183 billets de la classe « transféré ». Le seuil le moins coûteux pour ces coûts est 0,14 (7 470).
| Classe réelle | Signalés | Non signalés | Total |
|---|---|---|---|
| Transféré | 86vrai positif | 97faux négatif (manqué) | 183 |
| Non transféré | 141faux positif (fausse alerte) | 855vrai négatif | 996 |
| Total | 227 | 952 | 1 179 |
- Signalés
- 227
- sur 1 179 billets
- Précision
- 37,9 %
- 86 sur 227 signalés
- Rappel
- 47,0 %
- 86 sur 183
- Taux de faux positifs
- 14,2 %
- 141 sur 996
- Coût total
- 8 090
- minutes pour 1 179 billets
Description textuelle de l’explorateur
Le graphique du haut montre les deux mêmes panneaux de scores que le premier outil d’exploration, avec le seuil à 0,19. En dessous figurent la matrice de confusion, la précision, le rappel, le taux de faux positifs et le coût total. Deux champs numériques définissent les minutes pour un examen (valeur initiale : 10) et un transfert manqué (valeur initiale : 60).
Le graphique du bas montre le coût total des 1 179 billets de mai à chaque seuil. Avec les coûts initiaux, il atteint 10 980 minutes si aucun billet n’est signalé (183 transferts manqués × 60). À 0,19, il est de 8 090 minutes. Le seuil le moins coûteux est 0,14, avec 7 470 minutes. Il signale 345 billets (29,3 %), ce qui dépasse la capacité. Avec un transfert manqué de 30 minutes, le seuil le moins coûteux monte à 0,23 (163 billets signalés). Avec un transfert manqué de 120 minutes, il descend à 0,06 (686 billets signalés, soit 58,2 %).
Avec ces coûts, le seuil le moins coûteux est 0,14. Il signale 29,3 % des billets, mais l’équipe peut en examiner seulement 20 %. L’analyse des coûts ne change donc pas le seuil. Elle donne plutôt un argument à Grace : plus de temps d’agents expérimentés permettrait de détecter plus de transferts. Avec ces coûts approximatifs, ce temps supplémentaire serait rentable. Notez un autre point. Avec des scores calibrés, « signaler quand la probabilité dépasse 10 ÷ 60 = 0,17 » serait proche de la règle la moins coûteuse. Ici, le seuil le moins coûteux est plus bas, à 0,14, car les scores de mai sont trop faibles.
Tester une seule fois avec evaluate.py
Section intitulée « Tester une seule fois avec evaluate.py »Dans Données d’entraînement, de validation et de test, les données de test étaient l’examen final. Les nouvelles questions étaient dans une enveloppe scellée, ouverte une seule fois à la fin. Les autres personnes font confiance au résultat de cet examen, car aucun réglage n’a été fait en fonction de lui. Si un élève voit l’examen, s’exerce dessus et le reprend, le deuxième résultat ne veut rien dire.
Tous les choix sont maintenant faits. La leçon 1 a choisi les variables, la leçon 2 a choisi le modèle et ses réglages. Cette leçon a choisi le seuil, 0,19. Il est donc temps d’ouvrir l’enveloppe : les 1 002 billets de juin 2026 qu’aucune étape n’a utilisés. Priya l’ouvre une seule fois, avec un script qui refuse de s’exécuter une deuxième fois. Tomás demande : « Pourquoi un script? Tu pourrais juste calculer les nombres dans le carnet. » Un script rend le test identique à chaque exécution, écrit le résultat dans un fichier et peut empêcher une deuxième consultation. Une cellule de carnet peut être exécutée de nouveau par accident.
D’abord, train.py ajuste le pipeline sur les données d’entraînement et choisit le seuil sur les données de validation avec choose_threshold(). Il enregistre ensuite le modèle et le seuil dans model/. Vous l’écrirez vous-même dans Empaqueter les artefacts, au module 8. Pour l’instant, téléchargez le fichier du cours dans votre dossier de projet, puis exécutez-le :
curl -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/project/train.pypython train.pycurl.exe -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/project/train.pypython train.pyTrained on 16939 tickets. Threshold 0.19 for a review capacity of 20%.Valid: ROC AUC 0.752, average precision 0.391, flagged 227 of 1179 (19.3%), precision 0.379, recall 0.47.Saved model/escalation_model.joblib, model_info.json and check_sample.csv.Si vous voyez ModuleNotFoundError: No module named 'ticket_model' (module introuvable : aucun module nommé « ticket_model »), le terminal n’est pas dans ~/projects/ticket-model. Allez dans ce dossier et exécutez la commande de nouveau.
Écrivez maintenant evaluate.py dans le dossier du projet, à côté de train.py :
"""Report the saved model's results on the test set, once.
Nextia Learning, C05, Module 6, lesson 3 (Thresholds and calibration). Module 8uses the report again.
python evaluate.py
Uses the threshold that train.py chose on valid. Writesreports/test_report.json. If the report exists already, it stops: look atthe test set once, and do not change the model after you look."""
import jsonimport sysfrom pathlib import Path
import joblibfrom sklearn.metrics import average_precision_score, brier_score_loss, confusion_matrix, roc_auc_score
from ticket_model import FEATURES, TARGET, load
REPORT = Path("reports/test_report.json")
def main(): if REPORT.exists() and "--again" not in sys.argv: sys.exit(f"{REPORT} exists: the test set was used already. Read the report. " "Run with --again only to reproduce it, never to choose a change.") pipeline = joblib.load("model/escalation_model.joblib") info = json.loads(Path("model/model_info.json").read_text(encoding="utf-8")) test = load("test") scores = pipeline.predict_proba(test[FEATURES])[:, 1] flags = (scores >= info["threshold"]).astype(int) tn, fp, fn, tp = (int(v) for v in confusion_matrix(test[TARGET], flags, labels=[0, 1]).ravel()) rule = (test["priority"] == 1).astype(int) rule_tp = int((rule & test[TARGET]).sum()) report = { "rows": len(test), "escalated": int(test[TARGET].sum()), "threshold": info["threshold"], "roc_auc": round(roc_auc_score(test[TARGET], scores), 3), "average_precision": round(average_precision_score(test[TARGET], scores), 3), "brier": round(brier_score_loss(test[TARGET], scores), 4), "mean_score": round(float(scores.mean()), 3), "escalated_rate": round(float(test[TARGET].mean()), 3), "confusion": {"tp": tp, "fp": fp, "fn": fn, "tn": tn}, "flag_rate": round((tp + fp) / len(test), 3), "precision": round(tp / (tp + fp), 3), "recall": round(tp / (tp + fn), 3), "baseline_priority_1": {"flagged": int(rule.sum()), "flag_rate": round(float(rule.mean()), 3), "precision": round(rule_tp / rule.sum(), 3), "recall": round(rule_tp / test[TARGET].sum(), 3)}, } REPORT.parent.mkdir(exist_ok=True) REPORT.write_text(json.dumps(report, indent=2) + "\n", encoding="utf-8") print(json.dumps(report, indent=2))
if __name__ == "__main__": main()Chaque partie a un rôle :
| Lignes | Pourquoi |
|---|---|
if REPORT.exists() and "--again" not in sys.argv |
Le garde-fou. Une deuxième exécution s’arrête avec un message, pour éviter de refaire le test « juste une fois de plus » après un changement. --again reproduit le même rapport; cette option ne sert pas à choisir. |
joblib.load(...), model_info.json |
Le modèle et le seuil viennent de train.py. evaluate.py ne choisit rien. |
info["threshold"] |
Le seuil choisi sur les données de validation (0,19). Les données de test ne le définissent jamais. |
confusion_matrix(..., labels=[0, 1]) |
Les quatre comptes dans un ordre fixe, même si l’un d’eux vaut 0. |
baseline_priority_1 |
La règle sur les mêmes billets de test. Un nombre seul ne veut rien dire. |
brier, mean_score, escalated_rate |
La calibration sur les données de test, comme dans cette leçon. |
REPORT.write_text(...) |
Le rapport est un fichier dans reports/. Le résultat est donc conservé et peut être vérifié. |
Lisez l’avertissement, puis exécutez le script.
python evaluate.py{ "rows": 1002, "escalated": 157, "threshold": 0.19, "roc_auc": 0.749, "average_precision": 0.345, "brier": 0.1207, "mean_score": 0.123, "escalated_rate": 0.157, "confusion": { "tp": 70, "fp": 126, "fn": 87, "tn": 719 }, "flag_rate": 0.196, "precision": 0.357, "recall": 0.446, "baseline_priority_1": { "flagged": 150, "flag_rate": 0.15, "precision": 0.367, "recall": 0.35 }}Sur les données de test, le modèle signale 196 des 1 002 billets (19,6 %, dans la limite de capacité). Il détecte 70 des 157 transferts : le rappel est de 0,446. La règle en détecte 55 : son rappel est de 0,350. L’objectif d’amélioration est donc aussi atteint sur les données de test : au plus 20 % signalés et au moins 40 % détectés. La précision moyenne est de 0,345, contre 0,391 sur les données de validation : un peu plus faible. C’est normal. Les données de validation ont aidé à choisir, donc leur résultat est un peu optimiste, et juin est un nouveau mois. L’écart de calibration reste aussi présent : score moyen de 0,123, taux de 0,157. Nous ne changeons rien après avoir regardé.
Exécutez maintenant le script de nouveau, comme Tomás le ferait après « un petit changement » :
python evaluate.pyreports/test_report.json exists: the test set was used already. Read the report. Run with --again only to reproduce it, never to choose a change.C’est le garde-fou. Le rapport reste dans reports/test_report.json. La vérification du module ci-dessous et le module 8 le réutilisent.
Le test va-t-il dans le journal des expériences? Non. Le journal consigne les expériences : des essais en concurrence pour devenir le modèle, chacun évalué avec la même validation croisée. Le seuil et le test ne choisissent aucun modèle, donc aucun des deux n’a de ligne. Le seuil est enregistré avec le modèle dans model/model_info.json, et le résultat du test dans reports/test_report.json. Le journal se termine à E21, avec E15 comme modèle à conserver. Une nouvelle ligne exige de nouvelles données, par exemple un réentraînement avec mai et juin (module 8).
Vérification des connaissances
Section intitulée « Vérification des connaissances »Vérifiez votre compréhension
Pourquoi choisir le seuil sur les données de validation, et pourquoi choisir le seuil le plus bas qui respecte la capacité?
Afficher la réponse
Le seuil est un choix. Vous faites les choix sur les données de validation pour garder les données de test comme vérification finale fiable. Mai est aussi le mois qui suit le changement de politique. Il ressemble donc davantage à l’avenir que les données d’entraînement. Un seuil plus bas signale plus de billets et détecte donc au moins autant de transferts. Le seuil le plus bas respectant la capacité détecte donc le maximum de transferts que l’équipe peut examiner. Le seuil de 0,19 signale 227 billets (19,3 %); celui de 0,18 en signalerait 248 (21,0 %).
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Sur les données de validation, les billets dont les scores vont de 0,2 à 0,3 ont un score moyen de 0,241. Parmi eux, 31,5 % ont été transférés. Le modèle est-il trop confiant ou pas assez confiant dans cette plage? Enfreint-il la règle de capacité de 20 %?
Afficher la réponse
Pas assez confiant : le taux réel (31,5 %) dépasse le score (0,241), donc le modèle sous-estime le risque. Il n’enfreint pas la règle de capacité, car cette règle utilise seulement l’ordre des scores. Quand tous les scores sont trop faibles d’une valeur semblable, les mêmes billets restent les plus risqués. Ajouter 0,035 à chaque score laisse la précision moyenne à 0,391. Par contre, cela invalide toute utilisation du score comme probabilité, par exemple « probabilité de 24 % » sur un tableau de bord.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Omar lit le rapport de test (précision moyenne de 0,345, rappel de 0,446 avec 19,6 % signalés). Il demande : les données de validation donnaient une précision moyenne de 0,391 et un rappel de 0,470. Devrait-on baisser le seuil pour retrouver 0,470 en juin? Que répondez-vous?
Afficher la réponse
Non. Le seuil a été choisi sur les données de validation. Le rapport de test donne une estimation fiable pour les nouveaux billets. Si nous changeons le seuil à cause du résultat du test, les données de test deviennent un deuxième jeu de validation. Leurs résultats ne sont alors plus fiables. Un résultat de test inférieur à celui de validation est normal : la validation a aidé à choisir, et juin est un nouveau mois. Le modèle atteint toujours l’objectif sur les données de test : 19,6 % signalés, rappel de 0,446 contre 0,350 pour la règle. Nous présentons ces nombres tels quels. Un changement exige de nouvelles données : des billets étiquetés datant d’après juin.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Exercice du module
Section intitulée « Exercice du module »L’exercice du module vous demande de régler un petit espace de recherche et de choisir un seuil selon une capacité d’examen. Vous reprenezz tout le flux de travail de Régler les hyperparamètres et de cette leçon. Vous utilisez une nouvelle capacité, sans les données de test.
Exemple détaillé : le flux de travail de Priya pour 20 %
Section intitulée « Exemple détaillé : le flux de travail de Priya pour 20 % »| Étape | Données | Décision | Preuve |
|---|---|---|---|
| Variables | Validation croisée sur les données d’entraînement | Ajouter prior_escalations_90d; jamais les deux fuites |
Précision moyenne en validation croisée de 0,327 à 0,339, plus élevée sur chaque pli |
| Métrique | (la décision) | Rappel à un taux de signalement d’au plus 20 %; précision moyenne pour comparer les modèles | Capacité de Grace : 1 billet sur 5 |
| Réglage | Validation croisée sur les données d’entraînement | Régression logistique, C = 1 | Meilleur résultat : 0,3424 ± 0,0080; la régression logistique à 0,3393 est à moins d’une erreur-type |
| Seuil | Données de validation (mai) | 0,19 | 227 signalés (19,3 %), rappel de 0,470, précision de 0,379 |
| Calibration | Données d’entraînement et de validation | Montrer les signalements aux agents, pas les scores | Entraînement calibré; mai sous-estimé (0,120 contre 0,155); garantie : pire résultat |
| Test | Données de test (juin), une seule fois | Aucun changement ensuite | Précision moyenne de 0,345, 19,6 % signalés, rappel de 0,446; règle : 0,350 |
Votre tâche : une capacité de 25 %
Section intitulée « Votre tâche : une capacité de 25 % »Grace pourrait ajouter un agent expérimenté à temps partiel. L’équipe pourrait alors examiner 25 % des billets. Préparez la recommandation dans le carnet, section 10 :
- Réglez ce petit espace de recherche avec
GridSearchCV, la validation croisée du cours et la précision moyenne :Cà 0,1 ou 1, etclass_weightàNoneou"balanced". ("balanced"donne plus de poids aux billets transférés pendant l’ajustement.) - Appliquez la règle d’une erreur-type et choisissez un réglage. Écrivez une phrase pour expliquer pourquoi.
- Choisissez le seuil pour une capacité de 25 % sur les données de validation avec
choose_threshold(). - Écrivez le nombre de billets signalés, le taux de signalement, la précision et le rappel sur les données de validation.
- Écrivez ce que vous ne faites pas, et pourquoi.
Afficher la réponse modèle
params mean_test_score std_test_score se rank_test_score {'model__C': 0.1, 'model__class_weight': None} 0.3391 0.0154 0.0069 2{'model__C': 0.1, 'model__class_weight': 'balanced'} 0.3364 0.0157 0.0070 4 {'model__C': 1, 'model__class_weight': None} 0.3393 0.0156 0.0070 1 {'model__C': 1, 'model__class_weight': 'balanced'} 0.3365 0.0162 0.0072 3Réglage. Le meilleur est C = 1 sans pondération des classes (0,3393, erreur-type de 0,0070). La limite est 0,3393 − 0,0070 = 0,3323, et les quatre réglages la dépassent : ils sont à égalité. Gardez le plus simple, le modèle par défaut, qui est le pipeline que vous avez déjà. Ses scores restent aussi proches des taux, contrairement à ceux du modèle équilibré.
default mean score 0.120 threshold 0.16 flagged 291 (24.7%) recall 0.557balanced mean score 0.415 threshold 0.59 flagged 287 (24.3%) recall 0.552Seuil. choose_threshold(scores, 0.25) donne 0,16 : 291 des 1 179 billets de mai signalés (**24,7 %). Il détecte 102 des 183 transferts (rappel de 0,557), avec une précision de 0,351. Par rapport au seuil de 0,19 à 20 % : 64 examens supplémentaires par mois et 16 transferts supplémentaires détectés. Le modèle équilibré exige un seuil différent (0,59) pour presque les mêmes billets. Cela le confirme : un seuil appartient à un modèle précis.
Ce que vous ne faites pas. Vous ne réexécutez pas evaluate.py pour 25 % et ne regardez pas les données de test pour « vérifier » 0,16. Le rapport de test reste celui du seuil de 0,19. Si Grace adopte 25 %, les preuves fiables sont le résultat de validation ci-dessus, puis le prochain mois étiqueté (module 8).
Vérification du module
Section intitulée « Vérification du module »Vérifiez votre compréhension
Rappel : nommez le rôle des données d'entraînement, de validation et de test au module 6, avec un nombre pour chacune.
Afficher la réponse
Les données d’entraînement servent à ajuster les modèles et à choisir les variables et les réglages par validation croisée stratifiée à 5 plis. La régression logistique avec C = 1 obtient une précision moyenne de 0,3393, à moins d’une erreur-type du meilleur résultat (0,3424). Les données de validation (mai) confirment les choix après le changement de politique et définissent le seuil. Il est de 0,19 pour la capacité de 20 % (227 signalés, rappel de 0,470). Les données de test (juin) donnent un seul rapport final, sans autre rôle : précision moyenne de 0,345, 19,6 % signalés, rappel de 0,446.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Expliquer ou prédire : en juillet, le taux de transfert pour la garantie augmente encore, mais la part de chaque équipe reste identique. Le modèle et le seuil de 0,19 ne changent pas. Prédisez le taux de signalement et la précision. Dites lequel vous pouvez vérifier avant l'arrivée des étiquettes de juillet.
Afficher la réponse
Le taux de signalement reste à peu près identique (près de 19 %). Il dépend seulement des scores, qui dépendent seulement des variables, et celles-ci ne changent pas. La précision monte, car davantage de billets signalés sont transférés. Les scores du modèle sous-estiment maintenant encore plus le risque. Vous pouvez vérifier le taux de signalement le jour où les billets arrivent. La précision et le rappel exigent les étiquettes, qui arrivent 72 heures ou plus après. C’est pourquoi le module 8 surveille d’abord le taux de signalement.
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Vérifiez votre compréhension
Vérification finale : rédigez le rapport sur les données réservées pour Grace en quatre ou cinq phrases. Utilisez le rapport de test et dites ce que vous n'en ferez pas.
Afficher la réponse
Une réponse modèle : « Le modèle de transfert est une régression logistique avec 11 variables, choisie par validation croisée à 5 plis sur les billets de juillet 2024 à avril 2026. Un modèle de boosting par gradient ne le dépassait pas de plus d’une erreur-type. Son seuil, 0,19, a été choisi sur mai 2026 pour votre capacité de 20 %. Sur les billets de juin, utilisés une seule fois, il signale 19,6 % des billets et détecte 44,6 % des transferts (70 sur 157), avec une précision de 0,357. La règle de priorité 1 en détecte 35,0 %. Ses scores sous-estiment le risque depuis la politique de garantie (score moyen de 0,123 contre un taux de 0,157 en juin). Montrez donc les signalements aux agents, pas les scores. Nous ne changerons ni le seuil ni le modèle à cause de ces nombres. Le prochain changement utilisera des billets nouvellement étiquetés. »
Votre réponse contient-elle les points principaux de la nôtre ?
Connectez-vous et inscrivez-vous au cours pour enregistrer vos réponses. Chaque vérification compte pour le certificat.
Récapitulatif du module 6
Section intitulée « Récapitulatif du module 6 »Vous pouvez maintenant régler et finaliser un modèle honnêtement :
- Sélectionnez les caractéristiques avec trois questions. Connues au moment de la prédiction, information nouvelle, gain supérieur au bruit.
prior_escalations_90da satisfait ces critères (AP en validation croisée de 0,327 à 0,339); deux fuites semblaient trop bonnes (0,445 et 0,851) et n’ont jamais été utilisées. - Réglez les hyperparamètres par validation croisée sur les données d’entraînement. L’entraînement apprend les paramètres; vous choisissez les hyperparamètres avant. Utilisez une recherche par grille ou une recherche aléatoire, puis la règle d’une erreur-type. La régression logistique avec C = 1 fait jeu égal avec un modèle de boosting (amplification) supérieur de 0,0031.
- Choisissez le seuil sur les données de validation, selon la décision. Le seuil le plus bas qui respecte la capacité : 0,19, avec 227 billets signalés et un rappel de 0,470.
predict()utilise 0,5 et signale 2,1 %. - Distinguez le classement des probabilités. Le classement reste valable après le changement de politique; les scores, interprétés comme des probabilités, ne le sont plus.
- Consultez les données de test une seule fois.
evaluate.pya rapporté une AP de 0,345, 19,6 % de billets signalés et un rappel de 0,446. Faire des choix sur un jeu de données gonfle son score (0,411 contre 0,389 dans la simulation). - Notez chaque expérience dans le journal, avec ses résultats et sa raison, y compris les idées que vous avez rejetées. Le module 6 a ajouté E15 à E21; E15 est le modèle à conserver.
Revenir à un état connu
Section intitulée « Revenir à un état connu »Si vos fichiers de projet ou vos résultats diffèrent de ceux du module, revenez à l’état du cours. Exécutez ces commandes dans ~/projects/ticket-model, avec .venv actif.
python get_data.py --resetfor f in ticket_model.py train.py evaluate.py; do curl -fsSL -O https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/project/$f; donepython train.pypython evaluate.py --againpython get_data.py --resetforeach ($f in "ticket_model.py", "train.py", "evaluate.py") { curl.exe -fsSL -O "https://raw.githubusercontent.com/Nextia-Intelligence/nextia-learning-labs/main/C05/project/$f" }python train.pypython evaluate.py --againget_data.py --resettélécharge les données à nouveau et vérifie chaque fichier. La dernière ligne doit êtreReady: train 16939 rows (1983 escalated), valid 1179 (183), test 1002 (157).(Prêt : entraînement, 16 939 lignes, dont 1 983 transférées au niveau supérieur; validation, 1 179, dont 183; test, 1 002, dont 157.)- La ligne de téléchargement remplace vos trois fichiers de projet par ceux du cours.
train.pydoit afficherTrained on 16939 tickets. Threshold 0.19 for a review capacity of 20%.(Entraîné sur 16 939 billets. Seuil de 0,19 pour une capacité de révision de 20 %.)evaluate.py --againreproduit le rapport de test : précision moyenne de 0,345, rappel de 0,446. C’est permis ici, car aucun choix ne repose sur ce rapport.
Ne supprimez pas reports/test_report.json pour refaire le test « à neuf » après un changement. Une réinitialisation rétablit le modèle du cours; elle ne rend pas les données de test inconnues à nouveau. Dans un carnet (notebook) Jupyter, une nouvelle session (ou un nouveau dossier) part des fichiers téléchargés, sans réinitialisation nécessaire.
Récapitulatif
- Le seuil opérationnel est choisi sur les données de validation selon la décision : le plus bas qui respecte la capacité. Pour 20 % : 0,19, avec 227 billets signalés et un rappel de 0,470.
predict()utilise 0,5 et signale 2,1 %. - Un seuil appartient à un seul modèle. Un modèle équilibré nécessite 0,59 pour 25 %; le modèle par défaut nécessite 0,16.
- Calibration : sur les données d’entraînement, les scores correspondent aux taux (Brier de 0,0902). En mai, le modèle sous-estime les probabilités (moyenne de 0,120, taux de 0,155, Brier de 0,1155), surtout pour les billets de garantie. Le classement reste valable, donc le seuil lié à la capacité fonctionne encore; ne présentez pas les scores comme des probabilités sans recalibration.
evaluate.pya ouvert les données de test une seule fois, après tous les choix : AP de 0,345, 19,6 % de billets signalés, rappel de 0,446 contre 0,350 pour la règle. Rien ne change après cette consultation.- Le module 6 a choisi les caractéristiques, les réglages et le seuil avec les données d’entraînement et de validation. Le journal des expériences (E15 à E21) consigne chaque expérience et sa raison.
Ensuite, le module 7 examine les erreurs : quels billets le modèle manque et pour qui il fonctionne moins bien. Il demande aussi quand un modèle simple est le meilleur choix.
Leçon suivante : L'analyse par sous-groupes