Polydesk-logotype
Polydesk.ai — Header

ResNet (Residual Network)

ResNet (Residual Network) est une architecture de réseau de neurones convolutif introduite par Kaiming He et son équipe (Microsoft Research) en 2015. Son innovation fondamentale : les connexions résiduelles (skip connections) qui permettent au gradient de contourner des couches, rendant possible l’entraînement de réseaux de 50, 101, voire 152+ couches là où les réseaux précédents plafonnaient à 20-30 couches.

ResNet en bref
Auteurs
Kaiming He, Xiangyu Zhang, Shaoqing Ren, Jian Sun (Microsoft Research, 2015)
Paper
« Deep Residual Learning for Image Recognition » (CVPR 2016, Best Paper)
Innovation clé
Skip connections (connexions résiduelles) : y = F(x) + x
Résultat
Vainqueur ILSVRC 2015, top-5 error de 3.57%
Variantes
ResNet-18, 34, 50, 101, 152 ; ResNeXt, Wide ResNet, SE-ResNet
Influence
Présent dans tous les Transformers (GPT, BERT, ViT), AlphaFold, diffusion models
Frameworks
PyTorch (torchvision.models), TensorFlow/Keras, JAX

Le problème de la dégradation

Avant ResNet, la logique semblait simple : plus un réseau est profond, plus il peut apprendre de features complexes. En pratique, l’inverse se produisait. Des réseaux de 56 couches avaient une erreur d’entraînement (pas seulement de test) plus élevée que des réseaux de 20 couches. Ce n’était pas un problème de surapprentissage : le réseau profond était strictement moins bon même sur les données d’entraînement.

Ce phénomène, appelé problème de dégradation, est distinct du vanishing gradient (qui empêche la convergence). La dégradation signifie que le réseau converge, mais vers une solution sous-optimale. L’optimiseur ne parvient pas à trouver les bons poids dans un espace devenu trop complexe.

L’observation clé de He et al. : si un réseau de 56 couches ne peut pas au minimum reproduire les performances d’un réseau de 20 couches (en laissant les 36 couches supplémentaires apprendre la fonction identité), c’est que les couches non linéaires ont du mal à apprendre la transformation identité y = x. C’est paradoxal mais vrai : un empilement de convolutions + ReLU + BatchNorm a énormément de difficulté à apprendre « ne rien faire ».

La solution : les connexions résiduelles

Au lieu de demander à un bloc de couches d’apprendre directement la transformation souhaitée H(x), ResNet reformule le problème : le bloc apprend la fonction résiduelle F(x) = H(x) – x. La sortie du bloc est alors :

y = F(x) + x

Le terme + x est la skip connection (ou shortcut connection) : l’entrée du bloc est ajoutée directement à sa sortie, en contournant les couches internes.

Si la transformation optimale est proche de l’identité, le réseau n’a qu’à apprendre F(x) ≈ 0 (mettre les poids à zéro), ce qui est trivial. C’est beaucoup plus facile que d’apprendre la fonction identité complète à travers des couches non linéaires.

L’analogie du correcteur Imaginez que vous devez reproduire un document existant. Deux approches : réécrire le document en entier (ce que font les réseaux classiques), ou prendre le document original et n’écrire que les corrections nécessaires (ce que fait ResNet). La seconde approche est évidemment plus simple et moins sujette aux erreurs. C’est le principe du résiduel : apprendre la correction (F(x)), pas la sortie complète (H(x)).

Flux du gradient

L’addition dans y = F(x) + x crée un chemin direct pour le gradient. Lors de la rétropropagation, le gradient se propage à travers deux chemins : le chemin principal (à travers les couches) ET le raccourci (la skip connection). Même si le gradient s’atténue dans le chemin principal, il passe intact par le raccourci.

C’est cette propriété qui permet d’entraîner des réseaux de centaines de couches : le gradient peut toujours atteindre les couches basses via les skip connections, même si le chemin principal a des gradients faibles.

Les blocs résiduels

Basic Block (ResNet-18, ResNet-34)

Le bloc le plus simple : deux couches de convolution 3×3 empilées, chacune suivie de Batch Normalization et ReLU. La skip connection ajoute l’entrée directement à la sortie du bloc.

# Basic Block (simplifié)
# Entrée: x
# Conv 3x3 -> BN -> ReLU -> Conv 3x3 -> BN
# Sortie: F(x) + x -> ReLU

Ce bloc est utilisé dans ResNet-18 (8 basic blocks) et ResNet-34 (16 basic blocks). Suffisant pour les tâches de taille modérée.

Bottleneck Block (ResNet-50, 101, 152)

Pour les réseaux très profonds, le basic block devient trop coûteux en calcul. Le bottleneck block résout ce problème avec trois couches :

1. Convolution 1×1 : réduit le nombre de canaux (ex. 256 → 64). C’est le « goulot d’étranglement » (bottleneck).
2. Convolution 3×3 : effectue le travail principal sur les canaux réduits.
3. Convolution 1×1 : restaure le nombre de canaux (ex. 64 → 256).

# Bottleneck Block (simplifié)
# Entrée: x (256 canaux)
# Conv 1x1 (256 -> 64) -> BN -> ReLU
# Conv 3x3 (64 -> 64)  -> BN -> ReLU
# Conv 1x1 (64 -> 256)  -> BN
# Sortie: F(x) + x -> ReLU

Le bottleneck traite l’information dans un espace réduit (64 canaux au lieu de 256), ce qui divise le nombre de paramètres et de FLOPs tout en maintenant la capacité du réseau. ResNet-50 utilise 16 bottleneck blocks et atteint de meilleures performances que ResNet-34 (16 basic blocks) avec un coût computationnel comparable.

Projection shortcut

Quand les dimensions spatiales ou le nombre de canaux changent entre l’entrée et la sortie d’un bloc (par exemple lors d’un downsampling), une simple addition n’est plus possible. ResNet utilise alors une projection shortcut : une convolution 1×1 avec le stride approprié pour adapter les dimensions de l’entrée avant l’addition.

Les variantes de ResNet

Variante Année Innovation Intérêt
ResNet-v2 (Pre-activation) 2016 BN + ReLU avant la convolution (au lieu d’après) Meilleur flux de gradient. Permet d’entraîner 1000+ couches. Adopté par les Transformers (« pre-normalization »).
Wide ResNet (WRN) 2016 Moins de couches, plus de canaux par couche Meilleur compromis performance/GPU. Un WRN-28-10 bat ResNet-152 avec moins de couches.
ResNeXt 2017 Convolutions groupées avec cardinalité ajustable Meilleure performance que ResNet à coût computationnel égal. Introduit le concept de « cardinalité ».
SE-ResNet 2018 Module Squeeze-and-Excitation pour recalibrer les canaux Ajoute de l’attention sur les canaux. Gain notable pour un surcoût minime.
Stochastic Depth 2016 Suppression aléatoire de blocs résiduels pendant l’entraînement (DropPath) Régularisation puissante. Largement adoptée dans les Vision Transformers.
ConvNeXt 2022 ResNet modernisé avec les tricks des Transformers Rivalise avec les ViT. Prouve que le design résiduel CNN n’est pas obsolète.

La famille ResNet : choisir la bonne taille

Modèle Couches Paramètres Top-1 ImageNet Cas d’usage
ResNet-18 18 ~11.7M ~69.8% Embarqué, prototypage, petits datasets
ResNet-34 34 ~21.8M ~73.3% Bon compromis taille/performance
ResNet-50 50 ~25.6M ~76.1% Le standard. Backbone le plus utilisé.
ResNet-101 101 ~44.5M ~77.4% Tâches exigeantes, détection d’objets
ResNet-152 152 ~60.2M ~78.3% Performance maximale, serveurs puissants
ResNet-50 : le backbone universel ResNet-50 est probablement le modèle de deep learning le plus utilisé au monde. Il sert de backbone standard pour la détection d’objets (Faster R-CNN, Mask R-CNN), la segmentation (DeepLab, U-Net++), le transfer learning, et les benchmarks de recherche. Si vous ne savez pas quel CNN utiliser, commencez par ResNet-50.

Implémentation avec PyTorch

Utilisation d’un ResNet pré-entraîné (transfer learning)

import torch
import torch.nn as nn
import torchvision.models as models

# Charger ResNet-50 pré-entraîné sur ImageNet
model = models.resnet50(weights='IMAGENET1K_V2')

# Remplacer la dernière couche pour votre tâche
num_classes = 10  # ex: 10 types de défauts industriels
model.fc = nn.Linear(model.fc.in_features, num_classes)

# Option 1 : Fine-tuning complet
optimizer = torch.optim.Adam(model.parameters(), lr=1e-4)

# Option 2 : Feature extraction (geler le backbone)
for param in model.parameters():
    param.requires_grad = False
model.fc = nn.Linear(model.fc.in_features, num_classes)
optimizer = torch.optim.Adam(model.fc.parameters(), lr=1e-3)

print(f"Paramètres totaux : {sum(p.numel() for p in model.parameters()):,}")
print(f"Paramètres entraînables : {sum(p.numel() for p in model.parameters() if p.requires_grad):,}")

Bloc résiduel custom

class BasicBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super().__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, 3, 
                               stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.conv2 = nn.Conv2d(out_channels, out_channels, 3, 
                               padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        
        # Projection shortcut si les dimensions changent
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, 1, 
                         stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )
    
    def forward(self, x):
        identity = self.shortcut(x)   # Skip connection
        
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        
        out += identity               # Addition résiduelle
        out = self.relu(out)
        return out

L’influence de ResNet au-delà de la vision

La connexion résiduelle n’est pas restée confinée aux CNN. Elle est devenue un composant fondamental de quasiment toute architecture de deep learning moderne :

Transformers : chaque bloc Transformer (GPT, BERT, ViT) contient une connexion résiduelle. Sans elle, les Transformers de 100+ couches ne convergeraient pas. La variante pre-normalization (LayerNorm avant le bloc, comme dans GPT-2+) est directement inspirée de ResNet-v2.

AlphaFold : l’architecture de prédiction de structure protéique de DeepMind utilise massivement les connexions résiduelles dans son module Evoformer.

Modèles de diffusion : les U-Nets utilisés dans Stable Diffusion, DALL-E et Midjourney emploient des blocs résiduels dans chaque étage du réseau.

Highway Networks : une architecture parallèle (Srivastava, Greff, Schmidhuber, 2015) utilise des skip connections avec des portes apprenables. ResNet peut être vu comme un Highway Network avec des portes fixées à 1 (identité pure).

Cas d’usage concrets

Classification d’images : la tâche originale de ResNet. Depuis sa victoire à ILSVRC 2015, ResNet est devenu la référence pour le benchmarking en classification. En transfer learning, un ResNet-50 pré-entraîné sur ImageNet produit des résultats compétitifs sur des datasets spécialisés (plantes, maladies, textures industrielles) avec seulement quelques centaines d’images par classe.

Détection d’objets : ResNet-50 avec FPN (Feature Pyramid Network) est le backbone standard de Faster R-CNN et Mask R-CNN. Les features multi-échelle extraites par les différents stages du ResNet alimentent le FPN, qui produit des représentations à plusieurs résolutions pour détecter aussi bien les petits que les grands objets.

Segmentation sémantique : les architectures comme DeepLab v3+ et PSPNet utilisent un ResNet comme encodeur. Les skip connections du ResNet aident à préserver les détails spatiaux perdus lors du downsampling, ce qui est crucial pour la segmentation pixel par pixel.

Imagerie médicale : classification de radiographies (pneumonie, COVID-19, fractures), analyse de coupes histologiques, détection de tumeurs. Le transfer learning depuis ImageNet fonctionne remarquablement bien même sur des images médicales très différentes des photos naturelles.

Véhicules autonomes : les systèmes de perception utilisent des backbones ResNet pour la détection de piétons, véhicules, panneaux et obstacles en temps réel.

Extraction de features : les couches intermédiaires d’un ResNet pré-entraîné produisent des embeddings visuels riches, utilisables pour la recherche d’images similaires, le clustering visuel ou comme entrée pour d’autres modèles.

Limites de ResNet

Rendements décroissants en profondeur : ajouter des couches au-delà de 100-150 apporte des gains marginaux. Wide ResNet a montré qu’élargir le réseau (plus de canaux par couche) est souvent plus efficace qu’augmenter la profondeur. Le mythe « plus profond = meilleur » est une simplification.

Coût computationnel de ResNet-50 : avec ~4.1 GFLOPs et ~25.6M de paramètres, ResNet-50 est nettement plus lourd que des architectures modernes comme EfficientNet-B0 (~0.4 GFLOPs, ~5.3M paramètres) pour des performances comparables. Si l’efficacité compte, ResNet n’est plus le choix optimal.

Design statique : les skip connections de ResNet sont fixes (identité ou projection 1×1). Elles ne s’adaptent pas au contenu de l’image. Les architectures avec attention (SE-ResNet, Vision Transformers) offrent une adaptabilité dynamique que ResNet standard ne possède pas.

Pas d’attention globale : ResNet ne capture que les dépendances locales (limitées par le champ récepteur des convolutions). Pour les tâches nécessitant une compréhension globale de l’image, les Vision Transformers sont supérieurs.

Bonnes pratiques

Utilisez ResNet-50 pré-entraîné comme point de départ. C’est le backbone le plus fiable et le mieux documenté. Le transfer learning depuis ImageNet fonctionne remarquablement bien même sur des domaines très différents (imagerie médicale, satellite, industriel).

Fine-tuning progressif. Commencez par entraîner uniquement la dernière couche (feature extraction), puis dégeler progressivement les couches du backbone avec un learning rate faible (1e-5 à 1e-4). Cette approche est plus stable que le fine-tuning complet dès le départ.

Utilisez les poids IMAGENET1K_V2 dans PyTorch. Ce sont des poids réentraînés avec des techniques modernes (data augmentation avancée, optimiseur amélioré) qui donnent de meilleures performances que les poids V1 originaux (+3-4% top-1 sur ImageNet).

Considérez EfficientNet ou ConvNeXt si vous avez besoin de meilleures performances. ResNet-50 est un excellent point de départ, mais ces architectures plus récentes offrent un meilleur rapport performance/coût. EfficientNet-B0 est comparable à ResNet-50 avec 5x moins de paramètres.

Pour la détection d’objets, utilisez un ResNet-50 avec FPN (Feature Pyramid Network). C’est le backbone standard de Faster R-CNN et Mask R-CNN, et l’écosystème (Detectron2, MMDetection) le supporte nativement.


Questions fréquentes sur ResNet

Quelle est la différence entre une skip connection et une connexion résiduelle ?

Les deux termes sont souvent utilisés de manière interchangeable, mais il existe une nuance technique. Une « skip connection » est le terme générique pour toute connexion qui contourne une ou plusieurs couches. Une « connexion résiduelle » est une skip connection spécifique où l’entrée est ajoutée (addition élément par élément) à la sortie du bloc : y = F(x) + x. D’autres skip connections, comme celles de DenseNet, utilisent la concaténation au lieu de l’addition. Les connexions résiduelle de ResNet sont un cas particulier de skip connection.

Pourquoi ResNet-50 est-il plus utilisé que ResNet-152 ?

ResNet-50 offre le meilleur compromis entre performance et coût computationnel. Le gain de ResNet-101 par rapport à ResNet-50 est d’environ +1.3% en top-1 ImageNet, pour 1.7x plus de paramètres et de FLOPs. Le gain de ResNet-152 par rapport à ResNet-101 est encore plus marginal (+0.9%). Pour la plupart des applications pratiques (transfer learning, détection d’objets), ResNet-50 est suffisant et bien plus rapide à entraîner et à déployer.

ResNet est-il encore pertinent face aux Vision Transformers ?

Oui, dans plusieurs contextes. ResNet-50 reste le backbone standard pour le transfer learning sur des datasets de taille modérée, où son biais inductif (localité, invariance aux translations) compense le manque de données. Il est plus efficace sur edge et mobile que les ViT. ConvNeXt (un ResNet modernisé) rivalise avec les ViT sur ImageNet. Et surtout, la connexion résiduelle elle-même est omniprésente : tous les ViT l’utilisent. L’idée de ResNet survit dans toutes les architectures modernes.

Quelle est la différence entre le basic block et le bottleneck block ?

Le basic block empile deux convolutions 3×3 (utilisé dans ResNet-18 et 34). Le bottleneck block utilise trois convolutions : 1×1 (réduction de canaux), 3×3 (traitement), 1×1 (restauration de canaux). Le bottleneck est plus efficace en paramètres pour les réseaux profonds : ResNet-50 avec bottleneck a un coût computationnel similaire à ResNet-34 avec basic blocks, mais de meilleures performances. C’est pourquoi tous les ResNet de 50+ couches utilisent le bottleneck.

Comment les connexions résiduelles résolvent-elles le vanishing gradient ?

Lors de la rétropropagation, le gradient se propage par deux chemins à chaque bloc : le chemin principal (à travers les couches) et le raccourci (la skip connection). Même si le gradient s’atténue dans le chemin principal, il passe intact par le raccourci, car la dérivée de l’identité est 1. Le gradient total est la somme des deux chemins. Résultat : les couches basses du réseau reçoivent toujours un signal de gradient suffisant pour apprendre, même dans un réseau de 152 couches.

Polydesk.ai — Footer