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.

Rรฉsumez cet article avec :