Contrastive Learning : Guide Complet — Apprentissage par Contraste

Contrastive Learning : Guide Complet — Apprentissage par Contraste

Contrastive Learning : Guide complet — Apprentissage par Contraste

Résumé — Le Contrastive Learning est une méthode d’apprentissage auto-supervisé qui apprend des représentations visuelles de qualité sans aucune étiquette. En rapprochant les représentations de deux versions augmentées de la même image (paires positives) et en éloignant celles d’images différentes (paires négatives), le modèle développe une compréhension profonde de la sémantique visuelle. SimCLR, MoCo et BYOL ont démontré que cette approche rivalise avec le supervisé sur des tâches classiques de vision.


Principe mathématique

1. InfoNCE Loss

La fonction de coût centrale du Contrastive Learning est le Normalized Information Noise-Contrastive Estimation (InfoNCE) :

$$L = -\log \frac{\exp(\text{sim}(z_i, z_j) / \tau)}{\sum_{k=1}^{2N} \mathbb{1}_{[k \neq i]} \exp(\text{sim}(z_i, z_k) / \tau)}$$

Où :
z_i, z_j : projections de deux vues augmentées de la même image (paire positive)
sim(u,v) : similarité cosinus = (u · v) / (||u|| · ||v||)
τ : température, contrôle la netteté de la distribution (typiquement 0.07-0.5)
2N : tous les échantillons du batch (chaque image a 2 vues, donc N images = 2N vues)
– Le dénominateur inclut toutes les autres vues comme négatifs

2. Architecture SimCLR

SimCLR utilise un pipeline en trois étapes :
1. Augmentation : pour chaque image $x$, créer deux vues augmentées $\tilde{x}_i$ et $\tilde{x}_j$ (crop, couleur, flou)
2. Encodeur : f(x) extrait les features (ResNet-50) → h = f(x) ∈ R^d
3. Tête de projection : g(h) = W_2 · ReLU(W_1 · h) → z ∈ R^128

Après pré-entraînement, on jette g() et on utilise f(x) comme extracteur de features pour des tâches en aval.

3. MoCo (Momentum Contrast)

MoCo résout le problème de la taille de batch (SimCLR nécessite des milliers d’échantillons) en maintenant une queue de négatifs et un encodeur momentum :

$$k_{m} = m \cdot k_{m} + (1 – m) \cdot k$$

L’encodeur momentum k_m est une moyenne exponentiellement mobile de l’encodeur principal k. Cela garantit des représentations cohérentes pour les négatifs stockés dans la queue.


Intuition

Imaginez un enfant qui trie des photos sans connaître les noms des objets.

On lui donne deux photos du même chat — l’une recadrée sur la tête, l’autre avec des couleurs légèrement différentes. L’enfant apprend que ces deux photos viennent du même chat car elles se ressemblent malgré les modifications.

En même temps, il regarde des photos de chiens, de voitures, d’arbres — toutes différentes. Il apprend que ces images sont distinctes.

Sans jamais entendre le mot “chat”, l’enfant développe une représentation interne qui regroupe les vues similaires et sépare les vues différentes. C’est exactement ce que fait le Contrastive Learning.


Implémentation Python

1. SimCLR simple avec PyTorch

import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.transforms as transforms
from torchvision.models import resnet18


class SimCLR(nn.Module):
    def __init__(self, projection_dim=128):
        super().__init__()
        encoder = resnet18(weights=None)
        hidden_dim = encoder.fc.in_features
        encoder.fc = nn.Identity()
        self.encoder = encoder
        self.projection = nn.Sequential(
            nn.Linear(hidden_dim, hidden_dim),
            nn.ReLU(inplace=True),
            nn.Linear(hidden_dim, projection_dim),
        )

    def forward(self, x):
        h = self.encoder(x)
        z = self.projection(h)
        return F.normalize(z, dim=1)


def nt_xent_loss(z_i, z_j, temperature=0.5):
    batch_size = z_i.size(0)
    z = torch.cat([z_i, z_j], dim=0)
    similarity = z @ z.T / temperature

    mask = torch.eye(2 * batch_size, dtype=torch.bool, device=z.device)
    similarity = similarity.masked_fill(mask, float("-inf"))
    targets = (torch.arange(2 * batch_size, device=z.device) + batch_size) % (
        2 * batch_size
    )
    return F.cross_entropy(similarity, targets)


transform = transforms.Compose([
    transforms.RandomResizedCrop(224, scale=(0.2, 1.0)),
    transforms.RandomHorizontalFlip(),
    transforms.ColorJitter(0.8, 0.8, 0.8, 0.2),
    transforms.RandomGrayscale(0.2),
    transforms.GaussianBlur(kernel_size=9, sigma=(0.1, 2.0)),
    transforms.ToTensor(),
    transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])

model = SimCLR(projection_dim=128)
optimizer = torch.optim.Adam(model.parameters(), lr=3e-4)

# Exemple minimal exécutable avec deux vues synthétiques du même batch
batch_size = 16
x = torch.randn(batch_size, 3, 224, 224)
x_i = x + 0.05 * torch.randn_like(x)
x_j = x + 0.05 * torch.randn_like(x)

for epoch in range(3):
    z_i = model(x_i)
    z_j = model(x_j)
    loss = nt_xent_loss(z_i, z_j, temperature=0.5)
    optimizer.zero_grad()
    loss.backward()
    optimizer.step()
    print(f"Epoch {epoch + 1} | Loss: {loss.item():.4f}")

2. Évaluation par Linear Probing

from torch.utils.data import DataLoader, TensorDataset

for param in model.encoder.parameters():
    param.requires_grad = False

feature_dim = model.encoder(torch.randn(1, 3, 224, 224)).shape[1]
probe = nn.Linear(feature_dim, 10)  # ici 10 classes
probe_optimizer = torch.optim.Adam(probe.parameters(), lr=1e-3)
criterion = nn.CrossEntropyLoss()

images = torch.randn(32, 3, 224, 224)
labels = torch.randint(0, 10, (32,))
loader = DataLoader(TensorDataset(images, labels), batch_size=8, shuffle=True)

model.eval()
for epoch in range(3):
    epoch_loss = 0.0
    for x_batch, y_batch in loader:
        with torch.no_grad():
            features = model.encoder(x_batch)
        logits = probe(features)
        loss = criterion(logits, y_batch)
        probe_optimizer.zero_grad()
        loss.backward()
        probe_optimizer.step()
        epoch_loss += loss.item()
    print(f"Linear probing epoch {epoch + 1} | Loss: {epoch_loss / len(loader):.4f}")

Hyperparamètres

Hyperparamètre Valeur typique Description
temperature (τ) 0.07-0.5 Contrôle la netteté de la distribution (plus petit = plus discriminant)
batch_size 256-8192 Critique pour SimCLR (plus = plus de négatifs); MoCo pallie ce problème
projection_dim 128-256 Dimension de l’espace de projection (après le MLP)
encoder ResNet-50 Backbone pour l’extraction de features
learning_rate 1e-3-3e-4 Adam, souvent avec warmup de 10 epochs
epochs 200-1000 Le Contrastive Learning nécessite beaucoup d’epochs

Avantages

  1. Pas besoin d’étiquettes : Apprend directement à partir de données brutes, économisant des milliers d’heures d’annotation.
  2. Représentations génériques : Les features apprises se transfèrent à de multiples tâches (classification, détection, segmentation).
  3. Performance concurrentielle : SimCLR avec ResNet-50 atteint 76.5% top-1 sur ImageNet, proche des 77% du supervisé direct.
  4. Robustesse : Les représentations sont plus robustes aux corruptions et perturbations d’images que les modèles supervisés.

Limites

  1. Coût calcul élevé : SimCLR nécessite des milliers d’épochs et de gros batches. MoCo est plus efficace mémoire.
  2. Dépendance aux augmentations : Des augmentations trop faibles ne fournissent pas assez de variété; trop fortes et les paires positives deviennent trop différentes.
  3. Négatifs redondants : Dans un grand batch, la majorité des négatifs sont faciles (images très différentes), fournissant peu d’information.

4 cas d’usage concrets

1. Classification médicale avec peu de données labellisées

Pré-entraîné par Contrastive Learning sur 100 000 radiographies non labellisées, puis fine-tuné avec seulement 500 radiographies annotées pour détecter des pathologies. Les performances surpassent un modèle entraîné uniquement en supervisé avec les mêmes 500 exemples.

2. Recherche d’images par similarité

Un moteur de recherche e-commerce utilise les features extraites par un modèle SimCLR pour trouver des images visuellement similaires à une image requête. Les représentations contrastives capturent mieux la similarité sémantique que des features extraites d’un modèle supervisé classique.

3. Apprentissage de représentations audio

En adaptant les augmentations au domaine audio (time stretching, pitch shifting, ajout de bruit), le Contrastive Learning apprend des représentations robustes pour la reconnaissance de la parole ou la classification de sons environnementaux.

4. NLP auto-supervisé

Contrastive multi-task learning pour les représentations de phrases : deux versions d’une phrase (avec des mots supprimés différents) sont rapprochées, tandis que des phrases aléatoires sont éloignées. Cela complète les approches MLM comme BERT et améliore la robustesse des embeddings sur les tâches de similarité textuelle.


Comparaison des méthodes contrastives

Le domaine a évolué rapidement depuis SimCLR (2020). Voici les principales approches :

Méthodes avec négatifs (contraste explicite) :
SimCLR : gros batch pour beaucoup de négatifs, simples mais efficaces
MoCo (v1-v3) : queue de négatifs + encodeur momentum, efficace en mémoire
SupCon : Supervised Contrastive Learning, utilise les étiquettes pour créer plus de paires positives

Méthodes sans négatifs (contraste implicite) :
BYOL (Bootstrap Your Own Latent) : deux réseaux avec momentum, pas de négatifs nécessaires
SimSiam : encore plus simple, pas de momentum ni de négatifs, juste deux branches avec stop-gradient
DINO : auto-distillation avec un professeur et un élève, émergence spontanée de l’attention

Méthodes par reconstruction masquée :
MAE (Masked Autoencoder) : masque 75% de l’image et reconstruit les pixels, compétitif avec le contrastif
iBOT : combine distillation et reconstruction masquée


Conclusion

Le Contrastive Learning a inauguré l’ère de l’apprentissage auto-supervisé moderne. En apprenant des représentations riches sans aucune étiquette, il réduit drastiquement le besoin en annotations manuelles tout en maintenant des performances compétitives.

SimCLR et MoCo ont ouvert la voie à des méthodes encore plus avancées comme DINO (auto-distillation sans négatifs) et MAE (Masked Autoencoder), confirmant que l’avenir du learning profond est auto-supervisé.


Voir aussi


Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur la façon dont les données de vos commentaires sont traitées.