Qu'est-ce que l'apprentissage par transfert?
L'apprentissage par transfert est une technique d'utilisation d'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 lié. 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 d'autres poids de modèle de réseau pour réduire votre temps d'entraînement, car vous avez besoin de beaucoup de données pour entraîner 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 jeu de données pour entraîner la dernière couche.
Ensuite, dans ce didacticiel d'apprentissage PyTorch Transfer, nous allons apprendre à utiliser Transfer Learning avec PyTorch.
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 transfert d'apprentissage PyTorch, vous classerez un extraterrestre et un prédateur parmi 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 de Kaggle: Alien vs Predator.
Comment utiliser l'apprentissage par transfert?
Voici un processus étape par étape sur l'utilisation de Transfer Learning pour le Deep Learning avec PyTorch:
Étape 1) Chargez les données
La première étape consiste à charger nos données et à effectuer une transformation en images afin qu'elles correspondent aux exigences du réseau.
Vous allez charger les données à partir d'un dossier avec torchvision.dataset. Le module va itérer dans le dossier pour diviser les données pour le train et la validation. Le processus de transformation recadrera les images à partir du centre, effectuera un retournement horizontal, les normalisera et finalement les convertira en tenseur à l'aide du Deep Learning.
from __future__ import print_function, divisionimport osimport timeimport torchimport torchvisionfrom torchvision import datasets, models, transformsimport torch.optim as optimimport numpy as npimport matplotlib.pyplot as pltdata_dir = "alien_pred"input_shape = 224mean = [0.5, 0.5, 0.5]std = [0.5, 0.5, 0.5]#data transformationdata_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'].classesdevice = 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 = 4columns = 4fig=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 + meanplt.imshow(img)plt.show()
Étape 2) Définir le modèle
Dans ce processus de Deep Learning, vous utiliserez ResNet18 à partir du module torchvision.
Vous utiliserez torchvision.models pour charger resnet18 avec le poids pré-entraîné défini sur True. Après cela, vous gèlerez les calques afin que ces calques ne puissent pas être entraînés. Vous modifiez également le dernier calque avec un calque linéaire pour répondre à nos besoins qui est de 2 classes. Vous utilisez également CrossEntropyLoss pour la fonction de perte multi-classes 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 de transfert PyTorch ci-dessous.
## Load the model based on VGG19vgg_based = torchvision.models.vgg19(pretrained=True)## freeze the layersfor param in vgg_based.parameters():param.requires_grad = False# Modify the last layernumber_features = vgg_based.classifier[6].in_featuresfeatures = list(vgg_based.classifier.children())[:-1] # Remove last layerfeatures.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 une partie de la fonction du didacticiel Transfer Learning 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 = datainputs = 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() - sinceprint('Training complete in {:.0f}m {:.0f}s'.format(time_elapsed // 60, time_elapsed % 60))return modeldef visualize_model(model, num_images=6):was_training = model.trainingmodel.eval()images_so_far = 0fig = 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 += 1ax = 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 + meanax.imshow(img)if images_so_far == num_images:model.train(mode=was_training)returnmodel.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 la formation, le modèle prendra l'entrée et prédira la sortie. Après cela, la sortie prévue sera passée au critère de calcul des 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.0044train Loss: 0.0078train Loss: 0.0141train Loss: 0.0221train Loss: 0.0306train Loss: 0.0336train Loss: 0.0442train Loss: 0.0482train Loss: 0.0557train Loss: 0.0643train Loss: 0.0763train Loss: 0.0779train Loss: 0.0843train Loss: 0.0910train Loss: 0.0990train Loss: 0.1063train Loss: 0.1133train Loss: 0.1220train Loss: 0.1344train Loss: 0.1382train Loss: 0.1429train Loss: 0.1500Epoch 24/24----------train Loss: 0.0076train Loss: 0.0115train Loss: 0.0185train Loss: 0.0277train Loss: 0.0345train Loss: 0.0420train Loss: 0.0450train Loss: 0.0490train Loss: 0.0644train Loss: 0.0755train Loss: 0.0813train Loss: 0.0868train Loss: 0.0916train Loss: 0.0980train Loss: 0.1008train Loss: 0.1101train Loss: 0.1176train Loss: 0.1282train Loss: 0.1323train Loss: 0.1397train Loss: 0.1436train Loss: 0.1467Training complete in 2m 47s
Fin alors la sortie de notre modèle sera visualisée avec matplot ci-dessous:
Résumé
Alors, résumons tout! Le premier facteur est que PyTorch est un cadre d'apprentissage en profondeur en pleine croissance pour les débutants ou à des fins de recherche. Il offre un temps de calcul élevé, un graphique dynamique, la prise en charge des GPU et il est totalement écrit en Python. Vous pouvez définir facilement notre propre module de réseau et suivre le processus de formation avec une itération facile. Il est clair que PyTorch est idéal pour les débutants pour 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 aider le graphe dynamique.