Skip to main content

Welcome to a Grasp lesson

Create a free account to keep studying and create your own study path.

Lesson 84

Training Feedforward Neural Networks on Tabular Data

Recommended resources

Bonjour ! Dans les leçons précédentes, nous avons assemblé les briques fondamentales pour l'entraînement d'un réseau de neurones. Vous savez comment définir un modèle avec nn.Module, comment lui fournir des données via un DataLoader, comment le faire apprendre avec une boucle d'entraînement et comment mesurer ses performances avec une boucle d'évaluation.

Aujourd'hui, nous allons assembler toutes ces pièces pour construire et entraîner votre premier projet de deep learning de bout en bout. Nous prendrons un jeu de données tabulaires — similaire à ce que vous avez manipulé avec Pandas et Scikit-learn — et nous entraînerons un réseau de neurones pour effectuer une tâche de classification. Cette leçon est l'aboutissement de tout ce que vous avez appris jusqu'à présent, et elle vous donnera un plan de travail complet pour vos futurs projets.

La feuille de route d'un projet PyTorch

Avant de plonger dans le code, regardons la vue d'ensemble. Presque tous les projets de deep learning suivent un schéma similaire, magnifiquement illustré dans le diagramme ci-dessous.

Notre leçon d'aujourd'hui suivra précisément ce flux :

  1. Préparation des données : Charger, nettoyer et préparer nos données pour PyTorch.
  2. Définition du modèle : Construire l'architecture de notre réseau de neurones.
  3. Entraînement et validation : Implémenter la boucle qui entraîne et évalue le modèle.
  4. Évaluation finale : Utiliser le modèle entraîné pour faire des prédictions.

1. Préparation des données pour PyTorch

La première étape consiste à transformer nos données brutes en un format que PyTorch peut utiliser efficacement. Cela implique généralement plusieurs sous-étapes que vous avez déjà rencontrées dans les modules précédents.

  1. Chargement et division des données : On charge les données (par exemple, depuis un fichier CSV ou une bibliothèque comme Scikit-learn) et on les divise en ensembles d'entraînement et de test.
  2. Mise à l'échelle (Scaling) : Les réseaux de neurones sont sensibles à l'échelle des données. Il est donc crucial de normaliser ou standardiser les caractéristiques (features).
  3. Conversion en Tenseurs : PyTorch travaille avec des tenseurs. Nous devons donc convertir nos tableaux NumPy en tenseurs PyTorch.
  4. Création de Dataset et DataLoader : Ce sont les outils de PyTorch pour gérer les données.
    • Dataset est un objet qui encapsule nos données et permet d'y accéder par index.
    • DataLoader prend un Dataset et nous fournit des lots (batches) de données, ce qui est essentiel pour l'entraînement par descente de gradient stochastique.

La vidéo suivante est un excellent "crash course" qui met en œuvre toutes les étapes de cette leçon sur le jeu de données "Breast Cancer" de Scikit-learn.

Approfondissement : Créer un Dataset personnalisé

TensorDataset est pratique lorsque vos données tiennent déjà en mémoire sous forme de tenseurs. Cependant, pour des jeux de données plus grands ou plus complexes, vous créerez souvent votre propre classe Dataset en héritant de torch.utils.data.Dataset. C'est une compétence clé.

Pour cela, vous devez implémenter trois méthodes principales :

  • __init__(self, ...) : Le constructeur, où vous chargez vos données (par exemple, lire un fichier CSV avec Pandas).
  • __len__(self) : Doit retourner le nombre total d'échantillons dans votre jeu de données.
  • __getitem__(self, idx) : Doit retourner le i-ème échantillon (caractéristiques et étiquette) de votre jeu de données.

La vidéo suivante vous montre comment implémenter une telle classe pour un jeu de données tabulaires.


2. Définir le Modèle, la Perte et l'Optimiseur

Une fois les données prêtes, l'étape suivante consiste à définir les trois composants principaux de notre entraînement :

  1. Le Modèle : Nous allons définir une classe qui hérite de nn.Module. À l'intérieur, nous définirons nos couches (principalement des nn.Linear pour les données tabulaires) et la fonction forward qui décrit comment les données traversent le réseau.
  2. La Fonction de Perte (Criterion) : Elle mesure à quel point les prédictions du modèle sont erronées. Pour la classification binaire, nn.BCELoss (Binary Cross-Entropy Loss) ou nn.BCEWithLogitsLoss est le choix standard. BCEWithLogitsLoss est souvent préféré car il est numériquement plus stable (il combine une couche Sigmoid et la perte BCE).
  3. L'Optimiseur : C'est l'algorithme qui met à jour les poids du modèle pour minimiser la perte. optim.Adam est un choix très populaire et robuste qui fonctionne bien dans la plupart des cas.

Reprenons notre "crash course" vidéo pour voir comment ces trois éléments sont mis en place.


3. La Boucle d'Entraînement Complète

Nous arrivons au cœur du processus. C'est ici que nous allons itérer sur nos données, faire des prédictions, calculer la perte et mettre à jour le modèle, époque après époque. Les étapes à l'intérieur de la boucle d'entraînement sont maintenant familières.

Le code ci-dessous rassemble tout : une boucle sur les époques, et à l'intérieur de chaque époque, une boucle sur les lots de données fournis par le DataLoader.







# Définir le nombre d'époques
num_epochs = 20







# Mettre le modèle sur le bon appareil (CPU ou GPU)
model.to(device)

for epoch in range(num_epochs):






    # Mettre le modèle en mode entraînement
    model.train()
    running_loss = 0.0







    # Itérer sur les lots du DataLoader d'entraînement
    for inputs, labels in train_loader:






        # Mettre les données sur le bon appareil
        inputs, labels = inputs.to(device), labels.to(device)







        # 1. Mise à zéro des gradients de l'optimiseur
        optimizer.zero_grad()







        # 2. Passe avant : faire des prédictions
        outputs = model(inputs)







        # 3. Calculer la perte
        loss = criterion(outputs, labels)







        # 4. Rétropropagation : calculer les gradients
        loss.backward()







        # 5. Mise à jour des poids
        optimizer.step()







        # Accumuler la perte pour l'affichage
        running_loss += loss.item()
    






    # Afficher la perte moyenne pour l'époque
    print(f"Epoch {epoch+1}/{num_epochs}, Loss: {running_loss/len(train_loader)}")







    # (Optionnel mais recommandé) Exécuter une boucle d'évaluation sur le jeu de validation ici

La vidéo "Crash Course" implémente cette logique très clairement.


4. Évaluation et Prédiction

Une fois le modèle entraîné, il nous faut évaluer sa performance sur des données qu'il n'a jamais vues : l'ensemble de test. Cette boucle est plus simple car nous n'avons pas besoin de calculer de gradients ni de mettre à jour les poids. Comme nous l'avons vu dans la leçon précédente, nous utilisons with torch.no_grad(): et model.eval().

Enfin, pour faire une prédiction sur une nouvelle donnée, le processus est le même :

  1. Prétraiter la nouvelle donnée exactement de la même manière que les données d'entraînement (notamment la mise à l'échelle).
  2. La convertir en tenseur.
  3. La passer au modèle (en mode eval).

La dernière partie de la vidéo montre exactement cela.


Conclusion

Félicitations ! Vous avez maintenant parcouru toutes les étapes nécessaires pour mener à bien un projet de classification sur données tabulaires avec PyTorch. Vous disposez d'un modèle de travail que vous pouvez adapter à de nombreux autres problèmes.

Points clés à retenir :

  • Un projet PyTorch suit un flux structuré : préparation des données, définition du modèle, configuration de l'entraînement, boucle d'entraînement/évaluation, et utilisation du modèle.
  • Les données doivent être transformées en tenseurs et gérées avec les classes Dataset et DataLoader pour un entraînement efficace par lots.
  • Le modèle est défini comme une classe héritant de nn.Module, avec les couches dans __init__ et la logique de passe avant dans forward.
  • La boucle d'entraînement est le cœur du processus, orchestrant la passe avant, le calcul de la perte, la rétropropagation et la mise à jour des poids via l'optimiseur.
  • L'évaluation sur un jeu de test distinct, en mode model.eval() et torch.no_grad(), est cruciale pour mesurer la performance réelle du modèle.

Maintenant que vous maîtrisez les réseaux de neurones feedforward sur des données structurées, nous sommes prêts à explorer des architectures plus spécialisées. Dans la prochaine leçon, nous nous plongerons dans le monde de la vision par ordinateur en découvrant les réseaux de neurones convolutifs (CNNs), conçus spécifiquement pour traiter des données comme les images.