Tutoriel d'apprentissage par transfert PyTorch avec exemples

Qu'est-ce que l'apprentissage par transfert ?

Transfert d'apprentissage est une technique consistant à utiliser un modèle entraîné pour résoudre une autre tâche connexe. Il s'agit d'une méthode de recherche d'apprentissage automatique qui stocke les connaissances acquises lors de la résolution d'un problème particulier et utilise les mêmes connaissances pour résoudre un autre problème différent mais connexe. Cela améliore l'efficacité en réutilisant les informations recueillies à partir de la tâche précédemment apprise.

Il est courant d'utiliser une autre pondération de modèle de réseau pour réduire votre temps de formation, car vous avez besoin de beaucoup de données pour former un modèle de réseau. Pour réduire le temps de formation, vous utilisez d'autres réseaux et son poids et modifiez la dernière couche pour résoudre notre problème. L'avantage est que vous pouvez utiliser un petit ensemble de données pour entraîner la dernière couche.

Ensuite, dans ce didacticiel d'apprentissage PyTorch Transfer, nous apprendrons comment utiliser Transfer Learning avec PyTorch.

Chargement de l'ensemble de données

Chargement de l'ensemble de données

Source : Alien contre Predator Kaggle

Avant de commencer à utiliser Transfer Learning PyTorch, vous devez comprendre l'ensemble de données que vous allez utiliser. Dans cet exemple de Transfer Learning PyTorch, vous classerez un Alien et un Predator à partir de près de 700 images. Pour cette technique, vous n’avez pas vraiment besoin d’une grande quantité de données pour vous entraîner. Vous pouvez télécharger l'ensemble de données à partir de Kaggle : Alien contre prédateur.

Comment utiliser l’apprentissage par transfert ?

Voici un processus étape par étape sur la façon d'utiliser Transfer Learning pour le Deep Learning avec PyTorch :

Étape 1) Charger les données

La première étape consiste à charger nos données et à transformer les images afin qu'elles correspondent aux exigences du réseau.

Vous chargerez les données d'un dossier avec torchvision.dataset. Le module parcourra le dossier pour diviser les données pour l'entraînement et la validation. Le processus de transformation recadrera les images à partir du centre, effectuera un retournement horizontal, les normalisera et enfin les convertira en tenseur à l'aide du Deep Learning.

from __future__ import print_function, division
import os
import time
import torch
import torchvision
from torchvision import datasets, models, transforms
import torch.optim as optim
import numpy as np
import matplotlib.pyplot as plt

data_dir = "alien_pred"
input_shape = 224
mean = [0.5, 0.5, 0.5]
std = [0.5, 0.5, 0.5]

#data transformation
data_transforms = {
   'train': transforms.Compose([
       transforms.CenterCrop(input_shape),
       transforms.ToTensor(),
       transforms.Normalize(mean, std)
   ]),
   'validation': transforms.Compose([
       transforms.CenterCrop(input_shape),
       transforms.ToTensor(),
       transforms.Normalize(mean, std)
   ]),
}

image_datasets = {
   x: datasets.ImageFolder(
       os.path.join(data_dir, x),
       transform=data_transforms[x]
   )
   for x in ['train', 'validation']
}

dataloaders = {
   x: torch.utils.data.DataLoader(
       image_datasets[x], batch_size=32,
       shuffle=True, num_workers=4
   )
   for x in ['train', 'validation']
}

dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'validation']}

print(dataset_sizes)
class_names = image_datasets['train'].classes

device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")

Visualisons notre ensemble de données pour PyTorch Transfer Learning. Le processus de visualisation obtiendra le prochain lot d'images des chargeurs de données et des étiquettes du train et l'affichera avec matplot.

images, labels = next(iter(dataloaders['train']))

rows = 4
columns = 4
fig=plt.figure()
for i in range(16):
   fig.add_subplot(rows, columns, i+1)
   plt.title(class_names[labels[i]])
   img = images[i].numpy().transpose((1, 2, 0))
   img = std * img + mean
   plt.imshow(img)
plt.show()
Lot d'images
Lot d'images

Étape 2) Définir le modèle

Dans ce nouvel article concernant notre nouveau projet L'apprentissage en profondeur processus, vous utiliserez ResNet18 du module torchvision.

Vous utiliserez torchvision.models pour charger resnet18 avec le poids pré-entraîné défini sur True. Après cela, vous gelerez les calques afin qu’ils ne puissent pas être entraînés. Vous modifiez également le dernier calque avec un calque linéaire pour l'adapter à nos besoins, soit 2 classes. Vous utilisez également CrossEntropyLoss pour la fonction de perte multi-classe et pour l'optimiseur, vous utiliserez SGD avec un taux d'apprentissage de 0.0001 et un élan de 0.9, comme indiqué dans l'exemple d'apprentissage par transfert PyTorch ci-dessous.

## Load the model based on VGG19
vgg_based = torchvision.models.vgg19(pretrained=True)

## freeze the layers
for param in vgg_based.parameters():
   param.requires_grad = False

# Modify the last layer
number_features = vgg_based.classifier[6].in_features
features = list(vgg_based.classifier.children())[:-1] # Remove last layer
features.extend([torch.nn.Linear(number_features, len(class_names))])
vgg_based.classifier = torch.nn.Sequential(*features)

vgg_based = vgg_based.to(device)

print(vgg_based)

criterion = torch.nn.CrossEntropyLoss()
optimizer_ft = optim.SGD(vgg_based.parameters(), lr=0.001, momentum=0.9)

La structure du modèle de sortie

VGG(
  (features): Sequential(
	(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(1): ReLU(inplace)
	(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(3): ReLU(inplace)
	(4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
	(5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(6): ReLU(inplace)
	(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(8): ReLU(inplace)
	(9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
	(10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(11): ReLU(inplace)
	(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(13): ReLU(inplace)
	(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(15): ReLU(inplace)
	(16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(17): ReLU(inplace)
	(18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
	(19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(20): ReLU(inplace)
	(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(22): ReLU(inplace)
	(23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(24): ReLU(inplace)
	(25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(26): ReLU(inplace)
	(27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
	(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(29): ReLU(inplace)
	(30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(31): ReLU(inplace)
	(32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(33): ReLU(inplace)
	(34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
	(35): ReLU(inplace)
	(36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (classifier): Sequential(
	(0): Linear(in_features=25088, out_features=4096, bias=True)
	(1): ReLU(inplace)
	(2): Dropout(p=0.5)
	(3): Linear(in_features=4096, out_features=4096, bias=True)
	(4): ReLU(inplace)
	(5): Dropout(p=0.5)
	(6): Linear(in_features=4096, out_features=2, bias=True)
  )
)

Étape 3) Former et tester le modèle

Nous utiliserons certaines des fonctions de Transfer Learning Tutoriel PyTorch pour nous aider à former et à évaluer notre modèle.

def train_model(model, criterion, optimizer, num_epochs=25):
   since = time.time()

   for epoch in range(num_epochs):
       print('Epoch {}/{}'.format(epoch, num_epochs - 1))
       print('-' * 10)

       #set model to trainable
       # model.train()

       train_loss = 0

       # Iterate over data.
       for i, data in enumerate(dataloaders['train']):
           inputs , labels = data
           inputs = inputs.to(device)
           labels = labels.to(device)

           optimizer.zero_grad()
          
           with torch.set_grad_enabled(True):
               outputs  = model(inputs)
               loss = criterion(outputs, labels)

           loss.backward()
           optimizer.step()

           train_loss += loss.item() * inputs.size(0)

           print('{} Loss: {:.4f}'.format(
               'train', train_loss / dataset_sizes['train']))
          
   time_elapsed = time.time() - since
   print('Training complete in {:.0f}m {:.0f}s'.format(
       time_elapsed // 60, time_elapsed % 60))

   return model

def visualize_model(model, num_images=6):
   was_training = model.training
   model.eval()
   images_so_far = 0
   fig = plt.figure()

   with torch.no_grad():
       for i, (inputs, labels) in enumerate(dataloaders['validation']):
           inputs = inputs.to(device)
           labels = labels.to(device)

           outputs = model(inputs)
           _, preds = torch.max(outputs, 1)

           for j in range(inputs.size()[0]):
               images_so_far += 1
               ax = plt.subplot(num_images//2, 2, images_so_far)
               ax.axis('off')
               ax.set_title('predicted: {} truth: {}'.format(class_names[preds[j]], class_names[labels[j]]))
               img = inputs.cpu().data[j].numpy().transpose((1, 2, 0))
               img = std * img + mean
               ax.imshow(img)

               if images_so_far == num_images:
                   model.train(mode=was_training)
                   return
       model.train(mode=was_training)

Enfin, dans cet exemple d'apprentissage par transfert dans PyTorch, commençons notre processus de formation avec le nombre d'époques fixé à 25 et évaluons après le processus de formation. À chaque étape de formation, le modèle prendra en compte les entrées et prédira la sortie. Après cela, la production prévue sera transmise au critère permettant de calculer les pertes. Ensuite, les pertes effectueront un calcul de backprop pour calculer le gradient et enfin calculer les poids et optimiser les paramètres avec autograd.

Au niveau du modèle de visualisation, le réseau formé sera testé avec un lot d'images pour prédire les étiquettes. Ensuite, il sera visualisé à l'aide de matplotlib.

vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25)

visualize_model(vgg_based)

plt.show()

Étape 4) Résultats

Le résultat final est que vous avez atteint une précision de 92 %.

Epoch 23/24
----------
train Loss: 0.0044
train Loss: 0.0078
train Loss: 0.0141
train Loss: 0.0221
train Loss: 0.0306
train Loss: 0.0336
train Loss: 0.0442
train Loss: 0.0482
train Loss: 0.0557
train Loss: 0.0643
train Loss: 0.0763
train Loss: 0.0779
train Loss: 0.0843
train Loss: 0.0910
train Loss: 0.0990
train Loss: 0.1063
train Loss: 0.1133
train Loss: 0.1220
train Loss: 0.1344
train Loss: 0.1382
train Loss: 0.1429
train Loss: 0.1500
Epoch 24/24
----------
train Loss: 0.0076
train Loss: 0.0115
train Loss: 0.0185
train Loss: 0.0277
train Loss: 0.0345
train Loss: 0.0420
train Loss: 0.0450
train Loss: 0.0490
train Loss: 0.0644
train Loss: 0.0755
train Loss: 0.0813
train Loss: 0.0868
train Loss: 0.0916
train Loss: 0.0980
train Loss: 0.1008
train Loss: 0.1101
train Loss: 0.1176
train Loss: 0.1282
train Loss: 0.1323
train Loss: 0.1397
train Loss: 0.1436
train Loss: 0.1467
Training complete in 2m 47s

Terminez ensuite la sortie de notre modèle sera visualisée avec matplot ci-dessous :

Visualisé avec Matplot
Visualisé avec Matplot

Résumé

Alors, résumons tout ! Le premier facteur est que PyTorch est un framework d'apprentissage profond en pleine croissance pour les débutants ou à des fins de recherche. Il offre un temps de calcul élevé, un graphique dynamique, un support GPU et il est entièrement écrit en Python. Vous êtes capable de définir facilement votre propre module réseau et d’effectuer le processus de formation avec une itération simple. Il est clair que PyTorch est idéal pour les débutants qui souhaitent découvrir l'apprentissage en profondeur et pour les chercheurs professionnels, il est très utile avec un temps de calcul plus rapide et également la fonction autograd très utile pour assister les graphiques dynamiques.