ML Atlas

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.
De la leçon 1.1 : Qu’est-ce que l’apprentissage automatique ? Un modèle a raison environ 60 % du temps sur ces données de tumeurs. Pourquoi n’est-ce pas impressionnant ?

Voir la réponse

Bonne réponse : Parce que répondre toujours « bénigne » a déjà raison dans près des deux tiers des cas

La plupart des tumeurs du jeu de données sont bénignes, donc un modèle doit d’abord battre la réponse majoritaire triviale pour être utile.

De la leçon 1.1 : Qu’est-ce que l’apprentissage automatique ? Vous ajustez une règle jusqu’à ce qu’elle soit juste sur chaque exemple d’entraînement. Que vous apprend-elle sur la prochaine patiente ?

Voir la réponse

Bonne réponse : Très peu : seules des données jamais vues montrent comment elle traite de nouveaux cas

L’exactitude d’entraînement mesure l’ajustement aux cas connus ; seules des données mises de côté estiment la performance sur de nouveaux cas.

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.

Prédisez, puis vérifiez Même modèle, 20 découpages aléatoires différents (30 % des biopsies dans le test, soit 171). Dans quelle mesure le résultat de test varie-t-il d’un découpage à l’autre ?
Quel est votre degré de certitude ?

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.

1. Pourquoi le jeu de test doit-il rester intact jusqu’à la fin ?
Voir la réponse

Bonne réponse : Parce que sinon son score ne dit plus rien sur des données nouvelles

Dès que le jeu de test a influencé un choix, son score n’est plus un représentant honnête des données futures.

2. Vous changez seulement la graine aléatoire du découpage et l’exactitude de test bouge. Qu’est-ce que cela montre ?
Voir la réponse

Bonne réponse : Un score de test est une estimation qui dépend des lignes tombées dans le jeu de test

Des graines différentes donnent des lignes de test différentes, donc le score varie par hasard, d’autant plus que le jeu de test est petit.

3. Quel est le coût d’un très grand jeu de test ?
Voir la réponse

Bonne réponse : Le modèle a moins de lignes pour apprendre

Chaque ligne déplacée vers le jeu de test manque au modèle pour apprendre, donc un jeu de test plus grand signifie un modèle moins bien entraîné.

À 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).

  • n est le nombre de lignes de test, pas la taille du tableau entier.
  • SE diminue comme √n : quatre fois plus de lignes de test la divisent par deux.
  • Elle est maximale à p = 0.5 et diminue quand p s’approche de 0 ou de 1.
  • Environ deux tiers des scores tombent à moins d’une SE de p, et environ 95 % à moins de deux.
  • Cette SE ne 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.

Pour les praticiens
  • Découpez d’abord, puis ajustez les scalers et les imputeurs uniquement sur les lignes d’entraînement. Une Pipeline le fait pour vous et garde les lignes de test hors de chaque étape ajustée.
  • Fixez random_state pour 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.

Aller plus loin dans l’Atlas

Articles de l’encyclopédie sur les notions de cette leçon :