Architectures CNN : Classic → ResNet → ViT
“Détecteurs de motifs locaux qui voient les contours, puis les textures, puis les visages — en empilant des filtres”
CNN de zéro : convolution, pooling, champ réceptif, puis classic, Inception, ResNet (skip connections) et Vision Transformer (ViT).
Prérequis
Concepts Couverts
∑Formules Clés
Convolution
Glisser un noyau K sur l'entrée I, calculant des produits scalaires — détecte des motifs locaux
Taille de Sortie
H=hauteur, k=taille du noyau, p=rembourrage, s=foulée — détermine la résolution spatiale de sortie
Connexion Sautée ResNet
Connexion résiduelle : ajoute l'entrée directement à la sortie — résout le gradient évanescent en profondeur
▶Simulation Interactive
⬡Architecture du Modèle
Pourquoi la Structure Spatiale Importe
Aplatir une image 224×224 en vecteur perd toutes les relations spatiales — le pixel (0,0) n'a pas de relation spéciale avec (0,1) dans un réseau dense. Les CNN exploitent l'invariance par translation : le filtre qui détecte un bord horizontal fonctionne de la même façon que le bord soit en haut ou en bas de l'image. Ce partage des poids réduit drastiquement les paramètres et donne aux CNN leur biais inductif pour la vision.
Hiérarchie des Caractéristiques : Des Bords aux Objets
Détecteurs couche 1 : bords orientés et blobs de couleur (filtres de type Gabor). Couche 2 : textures construites à partir de combinaisons de bords. Couche 3 : parties d'objets (roues, yeux, fenêtres). Couches finales : objets complets. Cette hiérarchie a été visualisée par Zeiler & Fergus (2013) avec des DeconvNets — on peut littéralement voir ce que chaque couche 'voit'.
Dans un CNN profond de 3 couches, chaque neurone de sortie a un champ récepteur de (k-1)·3+1 pixels — ex: trois couches 3×3 donnent un champ effectif 7×7, identique à une 7×7 mais avec moins de paramètres et plus de non-linéarités.
L'Opération de Convolution
Une convolution 2D fait glisser un noyau K×K sur l'entrée en calculant un produit scalaire à chaque position. Avec C_en canaux d'entrée et C_out canaux de sortie, on a C_en × C_out × K² paramètres — bien moins qu'une couche entièrement connectée (H·L·C_en × H·L·C_out paramètres).
ResNet : Résoudre le Problème de Dégradation
Ajouter plus de couches à un CNN simple ne devrait jamais nuire (mappage identité). Pourtant, les réseaux très profonds simples s'entraînaient moins bien. He et al. (2015) ont trouvé le coupable : la difficulté d'optimisation, pas le sur-ajustement. Les connexions résiduelles permettent au réseau d'apprendre les résidus F(x) = H(x) - x au lieu de H(x) directement. Si l'identité est le mappage optimal, le réseau pousse F(x) → 0. Cela rend l'entraînement de 100+ couches faisable.
Recette d'Entraînement Moderne (ResNet / EfficientNet)
Augmentation : RandomHorizontalFlip, RandomCrop, ColorJitter, MixUp/CutMix
Architecture : utiliser des poids pré-entraînés (ImageNet) — toujours mieux que l'initialisation aléatoire
Planning de dégel : geler le backbone, entraîner la tête pendant 5 époques, puis dégeler tout
Taux d'apprentissage : décroissance LR par couche (couches plus profondes = LR × 0.1 par bloc)
Régularisation : Dropout avant le FC final, weight decay 1e-4, label smoothing 0.1
Optimiseur : AdamW + CosineAnnealing avec échauffement
Fine-tuning d'EfficientNet pour Classification Personnalisée
import timm import torch.nn as nn import torch.optim as optim class="tok-comment"># ── Configuration ────────────────────────────────────────────────────── nb_classes = class="tok-num">10 class="tok-comment"># ex. jeu de données class="tok-num">10 classes class="tok-comment"># Charger EfficientNet-B4 pré-entraîné modele = timm.create_model( class="tok-str">'efficientnet_b4', pretrained=True, num_classes=class="tok-num">0 class="tok-comment"># Supprimer la tête de classification ) class="tok-comment"># Geler le backbone initialement for param in modele.parameters(): param.requires_grad = False class="tok-comment"># Tête personnalisée classificateur = nn.Sequential( nn.AdaptiveAvgPool2d(class="tok-num">1), nn.Flatten(), nn.BatchNorm1d(modele.num_features), nn.Dropout(class="tok-num">0.4), nn.Linear(modele.num_features, nb_classes) ) class="tok-comment"># Étape class="tok-num">1 : entraîner seulement la tête (LR élevé) optimiseur = optim.AdamW(classificateur.parameters(), lr=class="tok-num">1e-3) class="tok-comment"># ... entraîner pendant class="tok-num">5 époques class="tok-comment"># Étape class="tok-num">2 : dégeler + affiner tout (LR faible) for param in modele.parameters(): param.requires_grad = True optimiseur = optim.AdamW([ {class="tok-str">'params': modele.parameters(), class="tok-str">'lr': class="tok-num">1e-5}, {class="tok-str">'params': classificateur.parameters(), class="tok-str">'lr': class="tok-num">1e-4} ])
?Vérification des Connaissances
La progression est sauvegardée dans votre navigateur — aucun compte requis.
Besoin d'un ingénieur IA ou data scientist ?
Je conçois des modèles ML sur mesure, des agents IA, de la vision par ordinateur et de l'automatisation — de l'idée à la production.