Apprendre avec peu d'étiquettes
Dans presque tous les projets industriels, les données brutes abondent et les données étiquetées manquent : annoter demande un expert, un essai destructif, ou simplement du temps que personne n'a. Ce module rassemble les stratégies qui permettent d'apprendre quand même — et surtout, comment décider où dépenser un budget d'annotation limité.
📋 Au programme
1. Situer son problème
Le point de départ n'est pas « quelle méthode est la plus moderne » mais « de quoi est-ce que je dispose ».
Un modèle pré-entraîné existe sur un transfert / fine-tuning (section 2) domaine proche On PEUT annoter, mais c'est cher apprentissage actif (section 3) Beaucoup de données non annotées semi-supervisé (4), disponibles auto-supervisé (5) Des règles métier ou des heuristiques supervision faible (section 6) existent Les étiquettes existent mais sont bruitées apprentissage robuste au bruit (section 6) Un simulateur du phénomène est disponible données synthétiques, sim2real (section 7) Quelques exemples seulement, et un gros few-shot / zero-shot (section 8) modèle de fondation accessible
Ces approches se combinent, et l'ordre compte : commencer par le transfert, puis récupérer des représentations auto-supervisées sur les données non annotées dont on dispose, puis annoter activement les cas informatifs. C'est ce pipeline qui donne le meilleur résultat par euro dépensé.
2. Transfert : l'option par défaut
Le principe : un modèle entraîné sur des millions d'images a appris des représentations générales — contours, textures, formes — qui servent bien au-delà de sa tâche d'origine. On récupère ces représentations plutôt que de les réapprendre à partir de 2 000 images.
EXTRACTION DE FEATURES on fige tout le réseau, on récupère le vecteur de la couche
pénultième, on entraîne une régression logistique dessus.
Quelques centaines d'exemples suffisent. Très rapide, et
souvent MEILLEUR qu'un fine-tuning qui surapprendrait.
FINE-TUNING PARTIEL on dégèle les dernières couches et on affine avec un taux
d'apprentissage 10 à 100× plus faible que d'habitude.
Le bon compromis à partir de quelques milliers d'exemples.
FINE-TUNING COMPLET tout le réseau est réentraîné. Demande beaucoup de données,
sous peine d'OUBLI CATASTROPHIQUE : le réseau perd les
représentations générales qui faisaient sa valeur.import torch, torchvision as tv
from sklearn.linear_model import LogisticRegression
modele = tv.models.resnet50(weights="IMAGENET1K_V2")
modele.fc = torch.nn.Identity() # on retire la tête de classification
modele.eval()
with torch.no_grad(): # pas de gradient : on n'entraîne rien ici
F = torch.cat([modele(xb) for xb, _ in chargeur]) # (n, 2048) embeddings
clf = LogisticRegression(max_iter=2000, C=1.0).fit(F.numpy(), y)
# 300 images étiquetées suffisent souvent à dépasser 90 % sur une tâche simpleDeux points de vigilance. La distance entre domaines décide du succès : d'ImageNet vers des photographies industrielles, le transfert fonctionne très bien ; vers des images de tomographie, de microscopie ou de spectrogrammes, nettement moins — les statistiques de bas niveau n'ont rien à voir. Dans ce cas, un pré-entraînement auto-supervisé sur ses propres images non annotées (section 5) est supérieur. Et l'adaptation de domaine traite le cas où l'on a des étiquettes sur un domaine source et aucune sur le domaine cible : on y aligne les distributions de représentations (CORAL, DANN), ou l'on recalibre simplement les statistiques de normalisation sur les données cibles — souvent étonnamment efficace pour un effort minime.
3. Apprentissage actif
Principe : plutôt que d'annoter au hasard, laisser le modèle désigner les exemples dont l'annotation lui apprendrait le plus. La boucle est identique à celle de l'optimisation bayésienne (module 19) — un critère d'acquisition, une évaluation coûteuse, une mise à jour — et l'intuition est la même : on ne mesure pas là où l'on sait déjà.
Moindre confiance 1 - max p(y|x) : les cas où le modèle hésite le plus
Marge écart entre les deux meilleures classes. Souvent le meilleur
critère simple en classification multiclasse.
Entropie incertitude globale de la distribution prédite
Désaccord de comité plusieurs modèles votent ; on annote là où ils divergent.
Très bon avec un ensemble profond (module 10).
Diversité / core-set couvrir l'espace des représentations plutôt que se concentrer
sur une seule zone ambiguë
Incertitude épistémique cibler ce que le modèle IGNORE plutôt que ce qui est
intrinsèquement bruité — la distinction du module 10 est ici
décisive : annoter du bruit pur n'apporte rien.
Espérance de gain critère théoriquement optimal, coûteux à calculer
d'informationimport numpy as np
from sklearn.cluster import KMeans
rng = np.random.default_rng(0)
etiquetes = np.zeros(len(X), dtype=bool)
etiquetes[rng.choice(len(X), 100, replace=False)] = True # amorçage ALÉATOIRE
for tour in range(10):
modele.fit(X[etiquetes], y[etiquetes])
# 1. incertitude : la marge entre les deux classes les plus probables
P = modele.predict_proba(X[~etiquetes])
tries = np.sort(P, axis=1)
marge = tries[:, -1] - tries[:, -2] # petite marge = cas ambigu
# 2. on présélectionne les 500 plus ambigus…
candidats = np.where(~etiquetes)[0][np.argsort(marge)[:500]]
# 3. …puis on impose la DIVERSITÉ : un représentant par groupe
km = KMeans(n_clusters=50, n_init=5, random_state=0).fit(Z[candidats])
lot = [candidats[np.argmin(np.linalg.norm(Z[candidats] - c, axis=1))]
for c in km.cluster_centers_]
y[lot] = annoter(X[lot]) # LA seule étape coûteuse
etiquetes[lot] = True
print(f"tour {tour}: {etiquetes.sum()} étiquettes, "
f"score={modele.score(X_test_aleatoire, y_test_aleatoire):.3f}")4. Semi-supervisé
On exploite les données non étiquetées pour contraindre le modèle. Deux hypothèses le justifient : les points d'un même groupe dense partagent probablement une étiquette (hypothèse de cluster), et la frontière de décision passe dans les zones de faible densité — elle sépare les paquets plutôt que de les traverser.
- Pseudo-étiquetage — le modèle étiquette lui-même les cas où il est très confiant, et se réentraîne dessus. Simple et souvent efficace, mais il amplifie ses propres erreurs : une erreur confiante devient une étiquette d'entraînement, donc une erreur encore plus confiante. Indispensable de fixer un seuil de confiance élevé (0,95 et plus), de recalibrer les probabilités (module 8) et de vérifier la performance à chaque tour sur un jeu annoté.
- Régularisation par cohérence — exiger que deux versions augmentées de la même donnée reçoivent la même prédiction. C'est l'idée de FixMatch : une augmentation faible produit la pseudo-étiquette, une augmentation forte doit la reproduire. Le modèle apprend ainsi ce à quoi il doit être invariant, sans étiquette humaine. L'une des méthodes les plus efficaces en vision avec très peu d'étiquettes.
- Propagation sur graphe — construire un graphe de voisinage (module 18) et diffuser les étiquettes le long des arêtes, de proche en proche.
Une mise en garde honnête : le semi-supervisé peut dégrader la performance si ses hypothèses ne tiennent pas — classes qui se chevauchent fortement, ou données non étiquetées issues d'une distribution différente (un autre capteur, une autre période). Il faut donc toujours le comparer à la baseline purement supervisée sur le même jeu de test, et accepter de l'abandonner.
5. Auto-supervisé
Ici, on fabrique une tâche à partir des données elles-mêmes, sans aucune étiquette humaine, dans le seul but d'apprendre de bonnes représentations — qu'un petit modèle supervisé exploitera ensuite. C'est ce qui a permis de pré-entraîner sur des corpus gigantesques non annotés, et c'est à l'origine des grands modèles actuels.
- Contrastif (SimCLR, MoCo) — rapprocher dans l'espace de représentation deux vues augmentées d'une même donnée, éloigner celles de données différentes. Le choix des augmentations définit les invariances apprises : si l'on inclut des variations de couleur, le modèle apprendra à ignorer la couleur — ce qui est souhaitable pour reconnaître un objet, catastrophique pour trier des composants par code couleur.
- Masquage (BERT pour le texte, MAE pour l'image) — cacher une partie de l'entrée et la reconstruire. Plus stable que le contrastif, sans besoin de paires négatives.
- Prédiction de contexte — prédire la suite d'un signal, l'ordre de fragments, la rotation appliquée à une image.
C'est l'approche à privilégier quand on possède beaucoup de données brutes spécifiques — des millions de spectres, d'images de production, de journaux machine — et peu d'annotations : un pré-entraînement sur ses propres données bat généralement un transfert depuis un domaine éloigné.
6. Supervision faible et étiquettes bruitées
Supervision faible
Plutôt que d'annoter exemple par exemple, on écrit des fonctions d'étiquetage : des règles, des expressions régulières, des seuils métier, un modèle existant. Chacune est imprécise et ne couvre qu'une partie des données ; prises ensemble, elles se recoupent. Un modèle génératif (approche Snorkel) estime alors la fiabilité de chaque règle à partir de leurs accords et désaccords — sans connaître la vérité — et produit des étiquettes probabilistes pour tout le corpus.
from snorkel.labeling import labeling_function, PandasLFApplier, LabelModel
ABSTIEN, NEGATIF, POSITIF = -1, 0, 1
@labeling_function()
def contient_mot_cle(x):
return POSITIF if "remboursement" in x.texte.lower() else ABSTIEN
@labeling_function()
def montant_eleve(x):
return POSITIF if x.montant > 5000 else ABSTIEN
@labeling_function()
def client_historique(x):
return NEGATIF if x.anciennete_ans > 10 else ABSTIEN
L = PandasLFApplier([contient_mot_cle, montant_eleve, client_historique]).apply(df)
modele_etiquettes = LabelModel(cardinality=2).fit(L) # estime la fiabilité de chaque règle
y_probable = modele_etiquettes.predict_proba(L)[:, 1] # étiquettes PROBABILISTESTrois experts qui écrivent dix règles en une journée produisent souvent l'équivalent de plusieurs semaines d'annotation manuelle — et les règles se documentent, se versionnent et se corrigent, contrairement à des étiquettes figées.
Étiquettes bruitées
Elles sont la norme, pas l'exception : les jeux de référence publics eux-mêmes contiennent quelques pour cent d'erreurs. Les défenses efficaces :
- Pertes robustes — MAE, Huber ou perte symétrique plutôt qu'entropie croisée pure, qui sur-pénalise les exemples mal étiquetés (elle tend vers l'infini quand le modèle contredit fortement l'étiquette).
- Label smoothing — remplacer la cible 1 par 0,9 : le modèle cesse de chercher une certitude absolue, ce qui limite l'effet des étiquettes fausses.
- Co-teaching — entraîner deux réseaux qui s'échangent les exemples de faible perte, considérés comme plus fiables.
- Détecter les erreurs — un modèle entraîné en validation croisée et très confiant en désaccord avec l'étiquette signale un cas à re-vérifier.
cleanlabautomatise cette recherche.
from cleanlab.filter import find_label_issues
from sklearn.model_selection import cross_val_predict
proba = cross_val_predict(modele, X, y, cv=5, method="predict_proba")
suspects = find_label_issues(labels=y, pred_probs=proba, return_indices_ranked_by="self_confidence")
print(f"{len(suspects)} étiquettes suspectes sur {len(y)}")
# relire les 50 premières à la main : c'est souvent l'heure la mieux investie du projetCorriger 2 % d'étiquettes fausses rapporte souvent davantage que tout le réglage d'hyperparamètres — et le gain est permanent, puisqu'il porte sur les données et non sur un modèle.
7. Données synthétiques et simulation
Quand un simulateur du phénomène existe — et c'est fréquent en ingénierie (module 21) — il devient une source illimitée de données étiquetées, puisque la vérité terrain est connue par construction. Le problème est le fossé simulation-réalité : un modèle entraîné sur des images de synthèse échoue sur des images réelles à cause de différences subtiles de texture, de bruit et d'éclairage que l'œil humain ne remarque même pas.
- Randomisation de domaine — faire varier massivement, et même de façon exagérée, les paramètres non essentiels du simulateur : textures, éclairages, bruits, frottements, couleurs. Le monde réel devient alors « un cas parmi d'autres » du domaine d'entraînement, et le modèle apprend à ignorer ce qui varie. C'est la technique qui a permis les transferts sim2real les plus convaincants en robotique (module 20).
- Mélange et ajustement — pré-entraîner sur le synthétique, affiner sur un petit jeu réel. Très efficace, et souvent tout ce dont on a besoin.
- Génération par modèle — VAE, GAN, modèles de diffusion, ou LLM pour du texte. Utile pour équilibrer des classes rares, mais un modèle génératif n'invente rien : il recombine ce qu'il a vu. Entraîner massivement sur des données générées appauvrit progressivement la diversité.
- Confidentialité — les données synthétiques sont parfois présentées comme une solution au partage de données personnelles. À manier avec prudence : sans garantie formelle (confidentialité différentielle, module 27), un générateur peut mémoriser et restituer des enregistrements réels.
8. Few-shot et zero-shot
Les grands modèles pré-entraînés ont déplacé la frontière : un LLM (module 22) classe correctement du texte avec trois exemples dans son prompt, CLIP (module 18) reconnaît des catégories décrites en langage naturel sans aucun exemple étiqueté. Pour un prototype ou une tâche à faible volume, c'est souvent la solution la plus rapide — et elle permet surtout de tester la valeur du projet avant d'investir dans l'annotation.
Trois réserves. Le coût par prédiction reste élevé : un appel de modèle par exemple, contre quelques microsecondes pour une régression logistique. La performance plafonne en dessous de ce qu'atteint un petit modèle spécialisé bien entraîné, dès que le domaine est technique. Et la dépendance à un fournisseur externe pose des questions de confidentialité et de reproductibilité (module 27).
La trajectoire raisonnable est donc : démarrer en zero-shot pour valider l'intérêt, utiliser le grand modèle pour pré-annoter en faisant valider par un expert (ce qui divise le temps d'annotation par trois ou quatre), puis distiller le tout dans un petit modèle maison qui sera des milliers de fois moins cher à l'inférence.
9. Décider combien annoter
La question la plus utile du module se pose en euros : faut-il annoter mille exemples de plus, ou changer de modèle ? La courbe d'apprentissage y répond empiriquement — on entraîne sur des fractions croissantes des étiquettes disponibles et on extrapole.
import numpy as np
from sklearn.model_selection import learning_curve
from scipy.optimize import curve_fit
tailles, score_train, score_val = learning_curve(
modele, X, y, train_sizes=np.linspace(0.1, 1.0, 8),
cv=5, scoring="average_precision", n_jobs=-1)
# la performance suit typiquement une loi de puissance : erreur ≈ a·n^(-b) + c
def loi(n, a, b, c): return a * n ** (-b) + c
(a, b, c), _ = curve_fit(loi, tailles, 1 - score_val.mean(axis=1), p0=[1, 0.5, 0.05])
for n in (2_000, 5_000, 10_000):
print(f"{n} étiquettes → erreur prédite {loi(n, a, b, c):.3f}")
# c est l'erreur INCOMPRESSIBLE : si elle est déjà proche du score actuel,
# annoter davantage ne changera rien.La lecture décide de la suite. Si la courbe de validation monte encore nettement, annoter davantage est le meilleur investissement. Si elle a plafonné loin du niveau souhaité, le problème est ailleurs — variables insuffisantes, étiquettes bruitées, ou tâche intrinsèquement difficile — et mille annotations de plus ne changeront rien. C'est le même raisonnement que le diagnostic biais-variance du module 14, mais exprimé en budget.
Ce qu'il faut retenir du module
- Ordre d'attaque : transfert, puis auto-supervisé sur ses propres données brutes, puis annotation active.
- Avec très peu d'exemples, l'extraction de features battra souvent un fine-tuning complet.
- L'apprentissage actif cible l'incertitude épistémique, exige de la diversité dans les lots, et impose de garder un jeu de test tiré au hasard.
- Le semi-supervisé aide quand ses hypothèses tiennent — à vérifier contre la baseline supervisée.
- Des règles métier (supervision faible) valent souvent des semaines d'annotation manuelle.
- Nettoyer 2 % d'étiquettes fausses rapporte plus que tout le réglage d'hyperparamètres.
- Le synthétique s'évalue sur du réel, sans exception ; la randomisation de domaine réduit le fossé sim2real.
- Le zero-shot sert à valider la valeur du projet, puis à pré-annoter, puis à distiller.
- La courbe d'apprentissage transforme « faut-il annoter plus ? » en décision chiffrée.