Retour à l’accueil

Pourquoi les connexions résiduelles vieilles de dix ans alimentent encore toute l’IA (et pourquoi c’est un problème)

Les connexions résiduelles, introduites en 2015, sous-tendent pratiquement tous les modèles d'IA modernes, des transformateurs aux réseaux de diffusion. Cet article explore leur domination persistante, des exemples pratiques et le besoin urgent d'innovation architecturale.

Lecture audio non disponible dans ce navigateur
Pourquoi les connexions résiduelles vieilles de dix ans alimentent encore toute l’IA (et pourquoi c’est un problème)

Tags

Résumé rapide

Les connexions résiduelles, introduites en 2015, sous-tendent pratiquement tous les modèles d'IA modernes, des transformateurs aux réseaux de diffusion. Cet article explore leur domination persistante, des exemples pratiques et le besoin urgent d'innovation architecturale.

Pourquoi les connexions résiduelles vieilles d’une décennie alimentent encore toute l’IA (et pourquoi c’est un problème)

Dans le paysage de l’intelligence artificielle, rares sont les innovations qui se sont révélées aussi durables que la connexion résiduelle. Introduit en 2015 par des chercheurs de Microsoft, le concept de « connexions de contournement » ou « connexions résiduelles » a été une avancée majeure permettant aux réseaux de neurones de devenir plus profonds sans succomber au problème des gradients qui s’évanouissent. Aujourd’hui, près d’une décennie plus tard, les connexions résiduelles restent un élément fondamental dans pratiquement toutes les grandes architectures d’IA — des réseaux convolutionnels aux transformeurs, en passant par les modèles de diffusion et les grands modèles de langage. Cet article explore pourquoi les connexions résiduelles persistent, comment elles fonctionnent en pratique, et les préoccupations croissantes concernant leurs limites alors que l’IA atteint des dimensions sans précédent.

Le problème que les connexions résiduelles ont résolu

Avant les connexions résiduelles, entraîner des réseaux de neurones très profonds était notoirement difficile. À mesure que les réseaux devenaient plus profonds — ajoutant davantage de couches pour capturer des motifs complexes — les gradients utilisés pour mettre à jour les poids pendant la rétropropagation disparaissaient (devenant trop petits pour être utiles) ou explosaient (devenant trop grands). Il en résultait que la précision plafonnait, voire se dégradait avec davantage de couches, un phénomène connu sous le nom de « problème de dégradation ».

Les connexions résiduelles ont résolu ce problème en introduisant une idée simple mais élégante : permettre à l’entrée d’une couche de contourner une ou plusieurs couches intermédiaires et d’être ajoutée directement à la sortie. Mathématiquement, au lieu d’apprendre une transformation directe \( H(x) \), la couche apprend une transformation résiduelle \( F(x) = H(x) - x \), de sorte que la sortie devienne \( F(x) + x \). Cette connexion de contournement garantit que les gradients peuvent circuler directement à travers le réseau pendant la rétropropagation, préservant ainsi la force du signal même dans des réseaux comportant des centaines de couches.

L’impact a été immédiat. L’architecture ResNet de Microsoft, qui a introduit les connexions résiduelles, a remporté le concours ImageNet 2015 avec un réseau de 152 couches — bien plus profond que tout ce qui avait été réalisé auparavant. Cette avancée a ouvert l’ère de l’apprentissage profond qui a suivi.

Pourquoi les connexions résiduelles sont encore partout

Les connexions résiduelles ne sont pas une relique du passé ; elles sont un composant central de l’IA moderne. Voici pourquoi elles restent omniprésentes :

1. Elles permettent un entraînement stable à grande échelle

Chaque grande architecture actuelle repose sur les connexions résiduelles pour une optimisation stable. Dans les transformeurs (l’épine dorsale de modèles comme GPT, BERT et Llama), chaque sous-couche d’attention et de feed-forward est enveloppée dans une connexion résiduelle suivie d’une normalisation de couche. Cette conception, connue sous le nom de Pre-LN (normalisation avant la couche), a été affinée dans l’article original « Attention is All You Need » et reste la norme. De même, les modèles de diffusion comme Stable Diffusion utilisent des blocs résiduels dans leurs squelettes U-Net pour générer des images haute résolution.

2. Elles sont indépendantes de l’architecture

Les connexions résiduelles fonctionnent aussi bien dans les réseaux convolutionnels, les réseaux récurrents et les transformeurs. Elles ne sont liées à aucune formulation mathématique spécifique — juste un contournement additif. Cette flexibilité leur a permis de survivre à de multiples changements de paradigme en IA.

3. Elles sont peu coûteuses en calcul

Ajouter une connexion résiduelle ne nécessite qu’une addition élément par élément et aucun paramètre supplémentaire. Cela les rend très efficaces par rapport à d’autres techniques de régularisation ou d’optimisation, comme la normalisation par lots ou le dropout. Dans l’entraînement à grande échelle, où chaque opération compte, les connexions résiduelles sont un gain à coût nul.

4. Elles s’alignent sur l’inspiration biologique

Certains neuroscientifiques ont noté que les connexions résiduelles ressemblent aux « connexions de contournement » présentes dans le cortex visuel des mammifères, où l’information circule à la fois par des voies directes et indirectes. Cette plausibilité biologique a fait des connexions résiduelles un choix naturel pour les chercheurs cherchant à émuler le traitement cérébral.

Les coûts cachés de l’omniprésence

Malgré leur domination, les connexions résiduelles ne sont pas sans problèmes. Alors que les modèles d’IA atteignent des milliards et des billions de paramètres, les limites des connexions résiduelles deviennent de plus en plus évidentes.

1. Goulots d’étranglement de mémoire et de bande passante

Les connexions résiduelles nécessitent de stocker les activations intermédiaires pour la rétropropagation. Dans un réseau profond avec des centaines de couches, cela peut consommer d’énormes quantités de mémoire GPU. Par exemple, l’entraînement d’un modèle de 175 milliards de paramètres comme GPT-3 nécessite de stocker les activations pour chaque bloc résiduel, ce qui entraîne des empreintes mémoire dépassant ce que la plupart du matériel peut gérer. Des techniques comme le gradient checkpointing (ne stocker qu’un sous-ensemble d’activations) atténuent partiellement ce problème, mais ajoutent une surcharge de calcul.

2. Les gradients qui s’évanouissent réapparaissent dans les réseaux extrêmement profonds

Bien que les connexions résiduelles aident, elles n’éliminent pas complètement le problème des gradients qui s’évanouissent dans les réseaux ultra-profonds. Dans les modèles avec des milliers de couches (courants dans certaines tâches de vision), les gradients peuvent encore se dégrader à travers de nombreux blocs résiduels. Cela oblige les chercheurs à utiliser des astuces supplémentaires comme la « profondeur stochastique » (suppression aléatoire de blocs résiduels pendant l’entraînement) ou des programmes de taux d’apprentissage avec « échauffement ».

3. Elles encouragent la surparamétrisation

Les connexions résiduelles facilitent l’ajout de couches supplémentaires sans dégrader les performances, mais cela conduit souvent à une surparamétrisation. De nombreux modèles modernes sont bien plus grands que nécessaire, consommant une énergie et des ressources de calcul excessives. L’hypothèse du « ticket gagnant » suggère que seule une fraction des poids d’un réseau est réellement importante — les connexions résiduelles peuvent masquer cette redondance.

4. Elles sont une béquille, pas une solution

Les critiques soutiennent que les connexions résiduelles sont devenues une béquille qui permet aux chercheurs d’éviter de confronter des problèmes architecturaux plus profonds. Au lieu de concevoir des réseaux qui apprennent efficacement à partir de zéro, nous comptons sur les connexions de contournement pour masquer les instabilités d’entraînement. Cela a conduit à une prolifération d’architectures « de type ResNet » qui sont des modifications de la conception originale de 2015, plutôt que de véritables innovations.

Implémentation pratique : Construire un réseau résiduel

Pour comprendre les connexions résiduelles en pratique, implémentons un bloc résiduel simple et entraînons-le sur un ensemble de données jouet. Nous utiliserons PyTorch, le framework dominant pour la recherche en IA.

Prérequis

  • Python 3.8 ou supérieur
  • PyTorch 2.0 ou supérieur
  • Un GPU compatible CUDA (optionnel, mais recommandé pour l’entraînement)

Installation étape par étape

Commencez par installer Python et créez un environnement virtuel pour isoler les dépendances :

python3 -m venv resnet_env
source resnet_env/bin/activate

Installez maintenant PyTorch. Visitez [pytorch.org](https://pytorch.org) pour la dernière commande adaptée à votre système. Par exemple, pour CUDA 11.8 :

pip install torch torchvision --index-url https://download.pytorch.org/whl/cu118

Installez les bibliothèques supplémentaires :

pip install numpy matplotlib tqdm

Exemples d’utilisation

Créez un fichier nommé `residual_demo.py` avec le code suivant :

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
from tqdm import tqdm

# Définir un bloc résiduel de base
class ResidualBlock(nn.Module):
    def __init__(self, in_channels, out_channels, stride=1):
        super(ResidualBlock, self).__init__()
        self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(out_channels)
        self.relu = nn.ReLU(inplace=True)
        self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn2 = nn.BatchNorm2d(out_channels)
        
        # Connexion de contournement : ajuster les dimensions si nécessaire
        self.shortcut = nn.Sequential()
        if stride != 1 or in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
                nn.BatchNorm2d(out_channels)
            )
    
    def forward(self, x):
        out = self.relu(self.bn1(self.conv1(x)))
        out = self.bn2(self.conv2(out))
        out += self.shortcut(x)  # La connexion résiduelle
        out = self.relu(out)
        return out

# Construire un ResNet simple pour CIFAR-10
class SimpleResNet(nn.Module):
    def __init__(self, num_classes=10):
        super(SimpleResNet, self).__init__()
        self.conv1 = nn.Conv2d(3, 16, kernel_size=3, stride=1, padding=1, bias=False)
        self.bn1 = nn.BatchNorm2d(16)
        self.relu = nn.ReLU(inplace=True)
        self.layer1 = self._make_layer(16, 16, 2, stride=1)
        self.layer2 = self._make_layer(16, 32, 2, stride=2)
        self.layer3 = self._make_layer(32, 64, 2, stride=2)
        self.avgpool = nn.AdaptiveAvgPool2d((1, 1))
        self.fc = nn.Linear(64, num_classes)
    
    def _make_layer(self, in_channels, out_channels, num_blocks, stride):
        layers = [ResidualBlock(in_channels, out_channels, stride)]
        for _ in range(1, num_blocks):
            layers.append(ResidualBlock(out_channels, out_channels, stride=1))
        return nn.Sequential(*layers)
    
    def forward(self, x):
        x = self.relu(self.bn1(self.conv1(x)))
        x = self.layer1(x)
        x = self.layer2(x)
        x = self.layer3(x)
        x = self.avgpool(x)
        x = torch.flatten(x, 1)
        x = self.fc(x)
        return x

# Charger l’ensemble de données CIFAR-10
transform = transforms.Compose([
    transforms.RandomHorizontalFlip(),
    transforms.RandomCrop(32, padding=4),
    transforms.ToTensor(),
    transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))
])

trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)

testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False, num_workers=2)

# Initialiser le modèle, la fonction de perte, l’optimiseur
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
model = SimpleResNet().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4)
scheduler = optim.lr_scheduler.StepLR(optimizer, step_size=30, gamma=0.1)

# Boucle d’entraînement
num_epochs = 50
for epoch in range(num_epochs):
    model.train()
    running_loss = 0.0
    for inputs, labels in tqdm(trainloader, desc=f'Époque {epoch+1}/{num_epochs}'):
        inputs, labels = inputs.to(device), labels.to(device)
        optimizer.zero_grad()
        outputs = model(inputs)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.item()
    
    scheduler.step()
    print(f'Époque {epoch+1} Perte : {running_loss/len(trainloader):.4f}')

# Évaluation
model.eval()
correct = 0
total = 0
with torch.no_grad():
    for inputs, labels in testloader:
        inputs, labels = inputs.to(device), labels.to(device)
        outputs = model(inputs)
        _, predicted = torch.max(outputs, 1)
        total += labels.size(0)
        correct += (predicted == labels).sum().item()

print(f'Précision sur le test : {100 * correct / total:.2f}%')

Exécutez le script :

python residual_demo.py

Cela entraînera un petit ResNet sur CIFAR-10, démontrant comment les connexions résiduelles permettent un entraînement stable d’un réseau de 10 couches. Observez que même avec cette implémentation simple, le modèle converge de manière fiable — un résultat direct des connexions de contournement.

Pourquoi c’est un problème pour l’avenir

La dépendance aux connexions résiduelles n’est pas simplement une curiosité historique ; elle façonne activement la trajectoire de la recherche en IA. À mesure que les modèles deviennent plus grands, le coût de calcul lié au stockage des activations pour les connexions résiduelles devient un goulot d’étranglement majeur. La tendance récente vers les modèles « Mixture of Experts » (MoE), comme Mixtral 8x7B, répond partiellement à ce problème en n’activant qu’un sous-ensemble de paramètres par entrée, mais les connexions résiduelles restent présentes dans chaque bloc expert.

De plus, la domination des connexions résiduelles pourrait freiner l’innovation. Les chercheurs hésitent à proposer des architectures qui n’incluent pas de connexions de contournement, car elles sont considérées comme essentielles à la stabilité de l’entraînement. Cela crée un « minimum local » dans l’espace de conception — nous optimisons dans le paradigme résiduel plutôt que d’explorer des alternatives comme les « convolutions profondes », l’« attention linéaire » ou les « modèles d’espace d’état » (qui, ironiquement, utilisent également des connexions résiduelles dans leurs implémentations).

Alternatives à l’horizon

Plusieurs alternatives prometteuses émergent, bien qu’aucune n’ait encore détrôné les connexions résiduelles :

  • **Réseaux sans normalisateur (NFNet)** : Le NFNet de DeepMind supprime la normalisation par lots et les connexions résiduelles en utilisant une initialisation et des fonctions d’activation soigneusement calibrées. Il atteint une précision compétitive sur ImageNet sans connexions de contournement.
  • **Modèles d’équilibre profond (DEQ)** : Ceux-ci traitent le réseau comme un système de point fixe, éliminant le besoin de blocs résiduels explicites en itérant une seule couche jusqu’à l’équilibre.
  • **Modèles d’espace d’état (SSM)** : Des architectures comme Mamba utilisent une récurrence linéaire au lieu de l’attention, supprimant le besoin de connexions résiduelles dans la sous-couche d’attention. Cependant, elles utilisent encore des connexions de contournement dans d’autres parties.

Ces approches restent marginales, principalement parce que les connexions résiduelles sont si bien comprises et faciles à implémenter.

Conclusion

Les connexions résiduelles sont un témoignage de la puissance des idées simples en IA. Elles ont résolu un problème critique en 2015 et continuent de permettre les plus grands modèles aujourd’hui. Cependant, leur omniprésence est aussi un handicap. Alors que l’IA évolue vers des modèles de billions de paramètres, la surcharge mémoire et de calcul des connexions résiduelles deviendra un facteur limitant. Le domaine doit dépasser cette innovation vieille d’une décennie pour développer des architectures intrinsèquement stables, efficaces et évolutives sans dépendre des connexions de contournement comme d’une béquille.

Pour l’instant, les connexions résiduelles restent l’épine dorsale de l’IA — mais les fissures commencent à apparaître. La prochaine avancée pourrait venir non pas de l’amélioration des connexions résiduelles, mais de l’apprentissage à construire des réseaux qui n’en ont pas besoin du tout.

Sources

FAQ

De quoi parle cet article ?

Cet article traite de « Pourquoi les connexions résiduelles vieilles de dix ans alimentent encore toute l’IA (et pourquoi c’est un problème) » dans la catégorie Guides. Les connexions résiduelles, introduites en 2015, sous-tendent pratiquement tous les modèles d'IA modernes, des transformateurs aux réseaux de diffusion. Cet article explore leur domination persistante, des exemples pratiques et le besoin urgent d'innovation architecturale.

À qui cet article est-il utile ?

Il est utile aux lecteurs qui veulent comprendre les outils et usages de l’IA de façon pratique.

Que faire ensuite ?

Lisez l’article, vérifiez les sources indiquées, puis testez les idées pertinentes pour votre contexte.