Présentation du module nn de PyTorch pour les réseaux de neurones

Les composants de PyTorch pour l'apprentissage profond

PyTorch offre plusieurs modules clés pour le développement de réseaux de neurones :

  • torch : convertit les tenseurs en format GPU-compatible pour les calculs accélérés.
  • torch.autograd : construit automatiquement le graphe de calcul et dérive les gradiants.
  • torch.nn : bibliothèque de couches partagées et de fonctions de perte pour les réseaux.
  • torch.optim : implémente des algorithmes d'optimisation standards.

Fondations d'un réseau de neurones

Un réseau typique se compose de :

  • Couches : blocs de construction élémentaires.
  • Modèle : assemblage de couches formant l'architecture complète.
  • Fonction de perte : objectif à minimiser pour ajuster les paramètres.
  • Optimiseur : algorithme guidant la minimisation de la perte.

Le module torch.nn en détail

Construction du modèle avec nn.Module

Deux approches principales existent pour définir des couches : nn.Module et nn.functional. La première hérite de la classe Module, encapsule les définitions de couches et la méthode forward, et gère automatiquement les paramètres apprenables. En implémentant forward, la méthode backward est automatiquement calculée via autograd.

  • Les classes nn.Xxx s'intègrent avec nn.Sequential, contrairement aux fonctions nn.functional.xxx.
  • Les couches comme nn.Conv2d gèrent les poids et biais de manière interne, alors que les versions fonctionnelles nécessitent une gestion manuelle.
  • Pour les couches comme Dropout, l'utilisation de nn.Dropout permet une transition automatique entre modes entraînement et évaluation via model.eval(), ce que nn.functional.dropout ne fait pas.

En général, on utilise nn.Module pour les couches avec paramètres apprenables (convolution, linéaire), et nn.functional pour les activations et le pooling sans paramètres.

La classe nn.Sequential permet d'empiler des couches. Pour les nommer, on peut utiliser add_module.

import torch
from collections import OrderedDict

class ReseauPersonnalise(torch.nn.Module):
    def __init__(self):
        super(ReseauPersonnalise, self).__init__()
        self.bloc_conv = torch.nn.Sequential(OrderedDict([
            ("premiere_conv", torch.nn.Conv2d(3, 48, 5, padding=2)),
            ("activation_relu", torch.nn.ReLU()),
            ("sous_echantillonnage", torch.nn.MaxPool2d(3))
        ]))
        self.bloc_dense = torch.nn.Sequential(OrderedDict([
            ("couche_lineaire1", torch.nn.Linear(48*10*10, 256)),
            ("activation_tanh", torch.nn.Tanh()),
            ("couche_sortie", torch.nn.Linear(256, 8))
        ]))

Propagation avant et arrière

La méthode forward() connecte les couches d'entrée, cachées et sortie pour propager les données. La rétropropagation est déclenchée par perte.backward(), utilisant la règle de la chaîne des dérivées partieelles.

Processus d'entraînement

Pendant l'entraînement, le modèle doit être en mode train(), tandis que eval() désactive certains comportements comme le Dropout. Les gradients s'accumulent par défaut, il faut donc appeler optimiseur.zero_grad() avant chaque itération. Le cycle typique est :

  1. Calculer la perte à partir des prédictions.
  2. Appeler perte.backward() pour générer les gradients.
  3. Exécuter optimiseur.step() pour mettre à jour les paramètres.

Pour utiliser le GPU, on transfère le modèle et les données avec to(device). Le parallélisme multi-GPU est possible avec nn.DataParallel. Les paramètres apprenables sont accessibles via modele.parameters() ou modele.named_parameters().

Les entrées/sorties de forward() sont des Variable, car seul ce type supporte le calcul automatique de gradient. Pour des exemples individuels, on peut ajouter une dimension batch avec unsqueeze(0). Les fonctions de perte courantes incluent nn.MSELoss et nn.CrossEntropyLoss.

Exemple complet de réseau neuronal

import torch
import torch.nn as nn
import torch.nn.functional as F

class MonReseau(nn.Module):
    def __init__(self):
        super(MonReseau, self).__init__()
        self.couche_conv1 = nn.Conv2d(1, 12, 6)
        self.couche_conv2 = nn.Conv2d(12, 32, 6)
        self.couche_fc1 = nn.Linear(32 * 4 * 4, 256)
        self.couche_fc2 = nn.Linear(256, 128)
        self.couche_sortie = nn.Linear(128, 10)

    def forward(self, entree):
        sortie = F.max_pool2d(F.relu(self.couche_conv1(entree)), 2)
        sortie = F.max_pool2d(F.relu(self.couche_conv2(sortie)), 2)
        sortie = sortie.view(sortie.size(0), -1)
        sortie = F.relu(self.couche_fc1(sortie))
        sortie = F.relu(self.couche_fc2(sortie))
        sortie = self.couche_sortie(sortie)
        return sortie

# Initialisation du modèle
modele = MonReseau()
print(modele)

# Affichage des paramètres
for nom, param in modele.named_parameters():
    print(nom, ":", param.shape)

# Test avec une entrée aléatoire
entree_test = torch.randn(1, 1, 32, 32)
resultat = modele(entree_test)
print("Taille de sortie:", resultat.shape)

# Réinitialisation des gradients et passage avant
modele.zero_grad()
resultat.backward(torch.ones(1, 10))

# Calcul de la perte avec une cible simulée
cible = torch.arange(0, 10, dtype=torch.float)
criterion = nn.MSELoss()
perte = criterion(resultat, cible)
print("Gradient du biais de la première couche conv:", modele.couche_conv1.bias.grad)

# Mise à jour manuelle des paramètres (à titre d'exemple)
taux_apprentissage = 0.01
for p in modele.parameters():
    p.data -= p.grad.data * taux_apprentissage

Étiquettes: PyTorch nn réseaux de neurones apprentissage profond torch.nn

Publié le 15 juin à 01h28