Le machine learning en partant de zéro · Leçon 1.2 · 3 sur 33 leçons prêtes · 10 min
Données, variables, étiquettes et découpage
En bref
Un jeu de données est un tableau d’exemples, de variables et d’étiquettes. Pourquoi le jeu de test doit rester caché, et pourquoi sa taille compte.
Échauffement Deux questions de leçons précédentes. Une minute, sans jamais bloquer la leçon.
Si une professeure donne à sa classe exactement les questions de l’examen final et que tout le monde obtient la note maximale, qu’a mesuré l’examen ? La mémoire de ces questions, rien de plus. L’apprentissage automatique affronte ce problème à chaque fois, et sa solution est étonnamment simple : garder une partie des questions sous clé dans un tiroir.
Choisissez une réponse et votre degré de certitude.
Répondez pour débloquer le labo.
Labo interactif
Ce labo interactif fonctionne dans un navigateur avec JavaScript activé. Le texte qui l’entoure décrit ce qu’il montre.
Voir la réponse
Bonne réponse : Nettement : quelques points de pourcentage séparent le pire et le meilleur découpage
Avec 30 % dans le test, le résultat varie de 90,1 % à 96,5 % (6,4 points) alors que le modèle et les données sont les mêmes ; seule change la répartition des biopsies dans le test. Un seul score de test n’est donc pas la vérité absolue.
À vous de jouer
- Réglez le curseur de la part de test sur une petite valeur, puis faites passer le curseur de la graine par plusieurs positions. Observez combien l’exactitude de test change alors que le modèle et les données restent les mêmes.
- Réglez maintenant la part de test sur une grande valeur et refaites l’expérience avec la graine. L’exactitude de test saute-t-elle plus ou moins qu’avant ?
- Gardez la graine fixe et déplacez la part de test d’un bout à l’autre. Remarquez comme le nombre de lignes d’entraînement diminue à mesure que le jeu de test grandit.
- Trouvez la graine qui donne la meilleure exactitude de test – puis demandez-vous si vous auriez le droit de publier ce chiffre.
L’idée en quelques mots
Voyons maintenant ce que vous venez de manipuler, en termes simples.
Presque tous les jeux de données de ce cours sont des tableaux. Chaque ligne est un exemple : une tumeur, une patiente, un passager, un vin. Chaque colonne est une variable (feature) : une propriété mesurée, comme un rayon, une tension artérielle, un âge ou un taux d’alcool. Une colonne particulière contient l’étiquette (label) – la réponse que le modèle doit prédire, par exemple « maligne » ou « a survécu ». Un modèle est une règle qui associe les variables d’une ligne à son étiquette.
Avant tout apprentissage, on mélange les lignes et on les répartit. La plus grande partie, le jeu d’entraînement, sert au modèle pour apprendre. La plus petite, le jeu de test, est mise sous clé et utilisée une seule fois, à la fin, pour estimer comment le modèle se débrouillera sur des lignes qu’il n’a jamais vues. Elle joue le rôle des questions dans le tiroir.
Imaginez une cheffe qui met au point une nouvelle soupe. Elle goûte sans arrêt pendant la cuisson – c’est l’entraînement. Mais pour savoir si les clients l’aimeront, elle la sert à quelques personnes qui ne l’ont jamais goûtée et n’ont aucune raison d’être polies. Leur verdict, c’est le score de test. Si elle ne demandait qu’à elle-même, elle trouverait toujours sa soupe parfaite.
Pourquoi ça marche
Le jeu de test n’est utile que parce que le modèle ne l’a jamais vu. Tant que les lignes d’entraînement et de test viennent de la même source et ont été réparties au hasard, les lignes de test se comportent comme de futurs cas, et l’exactitude de test est une estimation honnête de l’exactitude future.
Mais ce n’est qu’une estimation, et c’est là ce que les débutants entendent rarement. Le score de test dépend des lignes qui sont tombées par hasard dans le jeu de test. Mélangez les données avec une autre graine aléatoire (seed) et vous obtenez un autre jeu de test, et un autre score – avec exactement le même modèle et les mêmes données. Avec un petit jeu de test, le score peut sauter sensiblement, car une poignée de lignes inhabituelles pèse lourd dans le pourcentage. La statistique donne un ordre de grandeur de cette fluctuation. Pour une exactitude p mesurée sur n lignes de test, l’erreur type vaut environ
SE ≈ √(p · (1 − p) / n)
si bien que quatre fois plus de lignes de test ne divisent la fluctuation que par deux. C’est pourquoi un score de test unique n’est jamais toute la vérité.
Il y a aussi un compromis. Chaque ligne placée dans le jeu de test est une ligne dont le modèle ne peut pas apprendre. Un énorme jeu de test donne une note fiable à un modèle qui a appris sur trop peu de données ; un minuscule jeu de test donne une note peu fiable à un modèle bien entraîné. On place couramment entre un cinquième et un tiers des lignes dans le jeu de test, et les leçons suivantes montreront des façons plus astucieuses de sortir de ce dilemme.
Erreur fréquente
L’erreur la plus tentante consiste à essayer beaucoup de découpages et à garder celui qui donne le plus beau score de test. Le jeu de test a alors servi à prendre une décision, et le score annoncé est trop optimiste. Une version plus discrète de la même erreur s’appelle la fuite de données (data leakage) : des informations des lignes de test se glissent dans l’entraînement, par exemple quand on calcule des moyennes pour normaliser ou pour remplir des valeurs manquantes sur tout le tableau avant de le découper. La règle est stricte : découper d’abord, puis tout faire avec les seules lignes d’entraînement.
Avec un découpage propre en main, nous pouvons enfin construire un vrai modèle. Dans la prochaine leçon, nous ajustons le plus simple qui existe – une droite à travers un nuage de points.
Quiz
Trois questions pour vérifier vos acquis. Choisissez une réponse ou dépliez la solution sous chaque question. Au clavier : les flèches choisissent, Entrée ou Espace valide.
À retenir
- Un jeu de données est un tableau : les lignes sont des exemples, les colonnes des variables, une colonne est l’étiquette.
- On découpe avant tout le reste ; le modèle apprend sur le jeu d’entraînement et il est noté une seule fois sur le jeu de test.
- Un score de test est une estimation : un autre découpage aléatoire donne un autre chiffre, surtout avec peu de lignes de test.
- Choisir le découpage au meilleur score, ou préparer les données sur tout le tableau, fait fuir le jeu de test dans l’entraînement.
Pour aller plus loin : formule, code, pratique
Les maths
Une exactitude de test est la moyenne de n résultats « juste ou faux ». Si l’exactitude vraie est p, le score que vous mesurez varie d’un découpage à l’autre avec une erreur standard SE ≈ √(p · (1 − p) / n).
nest le nombre de lignes de test, pas la taille du tableau entier.SEdiminue comme√n: quatre fois plus de lignes de test la divisent par deux.- Elle est maximale à
p = 0.5et diminue quandps’approche de 0 ou de 1. - Environ deux tiers des scores tombent à moins d’une
SEdep, et environ 95 % à moins de deux. - Cette
SEne couvre que le choix des lignes de test. Elle ne dit rien d’un décalage entre les données que vous avez et celles que vous rencontrerez plus tard.
En code (Python)
La configuration du lab : régression logistique sur les 10 variables « mean », 30 % des biopsies dans le jeu de test (171 lignes), 20 découpages différents :
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
X, y = load_breast_cancer(return_X_y=True, as_frame=True)
X = X.filter(like="mean ") # les 10 variables « mean », comme dans le lab
accs = []
for seed in range(20): # même modèle, 20 découpages différents
Xtr, Xte, ytr, yte = train_test_split(X, y, test_size=0.3, stratify=y, random_state=seed)
model = make_pipeline(StandardScaler(), LogisticRegression()).fit(Xtr, ytr)
accs.append(model.score(Xte, yte))
n, p = len(yte), float(np.mean(accs))
print(f"test rows: {n}")
print(f"test accuracy: min {min(accs):.1%}, max {max(accs):.1%}")
print(f"standard error: {np.sqrt(p * (1 - p) / n):.1%} (n={n}), {np.sqrt(p * (1 - p) / (4 * n)):.1%} (n={4 * n})")
Sortie
test rows: 171
test accuracy: min 90.6%, max 97.1%
standard error: 1.8% (n=171), 0.9% (n=684)
scikit-learn mélange autrement que le lab, donc le minimum et le maximum diffèrent légèrement des 90,1 % et 96,5 % du lab. Le 684 est hypothétique : il demande plus de lignes que les 569 des données, il ne fait donc que montrer la formule. Le message est le même : le score bouge de plusieurs points alors que le modèle et les données ne changent pas, et quadrupler les lignes de test divise l’erreur standard par deux.
Télécharger le notebook (.ipynb). Ouvrez-le dans Jupyter ou importez-le dans Google Colab ; il télécharge lui-même les données manquantes.
Pour les praticiens
- Découpez d’abord, puis ajustez les scalers et les imputeurs uniquement sur les lignes d’entraînement. Une
Pipelinele fait pour vous et garde les lignes de test hors de chaque étape ajustée. - Fixez
random_statepour qu’un résultat soit reproductible, mais choisissez-le une seule fois, avant de regarder les scores. Essayer des graines jusqu’à en trouver une qui plaît, c’est regarder le jeu de test. - Pour la classification, passez
stratify=y, afin qu’une classe rare ne disparaisse pas d’un petit jeu de test. - Les lignes qui vont ensemble doivent rester ensemble. Plusieurs lignes d’un même patient doivent toutes aller du même côté, et les données ordonnées dans le temps se découpent par date, pas au hasard. Sinon, le jeu de test fuit.
- Donnez un score avec sa taille de test, et pour de petites données, répétez le découpage ou utilisez la validation croisée (leçon 8) pour montrer la dispersion.
Cela vous a-t-il aidé ?
Merci ! Cela nous aide à nous améliorer.
Aller plus loin dans l’Atlas
Articles de l’encyclopédie sur les notions de cette leçon :