Εκμάθηση PyTorch Transfer Learning Tutorial με Παραδείγματα

Τι είναι η Transfer Learning;

Μεταφορά μάθησης είναι μια τεχνική χρήσης ενός εκπαιδευμένου μοντέλου για την επίλυση άλλης σχετικής εργασίας. Είναι μια μέθοδος έρευνας της Μηχανικής Μάθησης που αποθηκεύει τη γνώση που αποκτήθηκε κατά την επίλυση ενός συγκεκριμένου προβλήματος και χρησιμοποιεί την ίδια γνώση για να λύσει ένα άλλο διαφορετικό αλλά συναφές πρόβλημα. Αυτό βελτιώνει την αποτελεσματικότητα με την επαναχρησιμοποίηση των πληροφοριών που συγκεντρώθηκαν από την εργασία που μάθατε προηγουμένως.

Είναι δημοφιλές να χρησιμοποιείτε άλλο βάρος μοντέλου δικτύου για να μειώσετε τον χρόνο εκπαίδευσής σας, επειδή χρειάζεστε πολλά δεδομένα για να εκπαιδεύσετε ένα μοντέλο δικτύου. Για να μειώσετε τον χρόνο εκπαίδευσης, χρησιμοποιείτε άλλα δίκτυα και το βάρος του και τροποποιείτε το τελευταίο στρώμα για να λύσετε το πρόβλημά μας. Το πλεονέκτημα είναι ότι μπορείτε να χρησιμοποιήσετε ένα μικρό σύνολο δεδομένων για να εκπαιδεύσετε το τελευταίο επίπεδο.

Στη συνέχεια, σε αυτό το σεμινάριο εκμάθησης PyTorch Transfer, θα μάθουμε πώς να χρησιμοποιούμε το Transfer Learning με το PyTorch.

Φόρτωση σετ δεδομένων

Φόρτωση σετ δεδομένων

Πηγή: Alien vs. Predator Kaggle

Πριν ξεκινήσετε να χρησιμοποιείτε το Transfer Learning PyTorch, πρέπει να κατανοήσετε το σύνολο δεδομένων που πρόκειται να χρησιμοποιήσετε. Σε αυτό το παράδειγμα Transfer Learning PyTorch, θα ταξινομήσετε έναν Alien και έναν Predator από σχεδόν 700 εικόνες. Για αυτήν την τεχνική, δεν χρειάζεστε πραγματικά μεγάλο όγκο δεδομένων για εκπαίδευση. Μπορείτε να κατεβάσετε το σύνολο δεδομένων από Kaggle: Alien vs. Predator.

Πώς να χρησιμοποιήσετε το Transfer Learning;

Ακολουθεί μια διαδικασία βήμα προς βήμα σχετικά με τον τρόπο χρήσης της Transfer Learning για Deep Learning με το PyTorch:

Βήμα 1) Φορτώστε τα δεδομένα

Το πρώτο βήμα είναι να φορτώσουμε τα δεδομένα μας και να κάνουμε κάποια μετατροπή σε εικόνες έτσι ώστε να ταιριάζουν με τις απαιτήσεις δικτύου.

Θα φορτώσετε τα δεδομένα από έναν φάκελο με το torchvision.dataset. Η μονάδα θα επαναληφθεί στον φάκελο για να χωρίσει τα δεδομένα για εκπαίδευση και επικύρωση. Η διαδικασία μετασχηματισμού θα περικόψει τις εικόνες από το κέντρο, θα εκτελέσει μια οριζόντια αναστροφή, θα κανονικοποιήσει και, τέλος, θα τις μετατρέψει σε τανυστή χρησιμοποιώντας τη Βαθιά Μάθηση.

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")

Ας οπτικοποιήσουμε το σύνολο δεδομένων μας για το PyTorch Transfer Learning. Η διαδικασία οπτικοποίησης θα λάβει την επόμενη παρτίδα εικόνων από τους φορτωτές δεδομένων και τις ετικέτες του τρένου και θα την εμφανίσει με 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()
Παρτίδα εικόνων
Παρτίδα εικόνων

Βήμα 2) Ορισμός μοντέλου

Σε αυτή τη Βαθιά μάθηση διαδικασία, θα χρησιμοποιήσετε το ResNet18 από τη μονάδα torchvision.

Θα χρησιμοποιήσετε το torchvision.models για να φορτώσετε το resnet18 με το προ-εκπαιδευμένο βάρος που έχει οριστεί ως True. Μετά από αυτό, θα παγώσετε τα στρώματα έτσι ώστε αυτά τα στρώματα να μην μπορούν να εκπαιδεύονται. Μπορείτε επίσης να τροποποιήσετε το τελευταίο στρώμα με ένα Γραμμικό επίπεδο για να ταιριάζει με τις ανάγκες μας που είναι 2 τάξεις. Χρησιμοποιείτε επίσης το CrossEntropyLoss για συνάρτηση απώλειας πολλών κλάσεων και για τον βελτιστοποιητή θα χρησιμοποιήσετε SGD με ρυθμό εκμάθησης 0.0001 και ορμή 0.9 όπως φαίνεται στο παρακάτω παράδειγμα PyTorch Transfer Learning.

## 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)

Η δομή του μοντέλου εξόδου

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)
  )
)

Βήμα 3) Μοντέλο Εκπαίδευσης και Δοκιμής

Θα χρησιμοποιήσουμε μερικές από τις λειτουργίες από το Transfer Learning Εκμάθηση PyTorch για να μας βοηθήσει να εκπαιδεύσουμε και να αξιολογήσουμε το μοντέλο μας.

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)

Τέλος, σε αυτό το παράδειγμα Transfer Learning στο PyTorch, ας ξεκινήσουμε τη διαδικασία εκπαίδευσης με τον αριθμό των εποχών που έχει οριστεί σε 25 και ας αξιολογήσουμε μετά τη διαδικασία εκπαίδευσης. Σε κάθε βήμα εκπαίδευσης, το μοντέλο θα λάβει την είσοδο και θα προβλέψει την έξοδο. Μετά από αυτό, η προβλεπόμενη παραγωγή θα περάσει στο κριτήριο για τον υπολογισμό των απωλειών. Στη συνέχεια, οι απώλειες θα εκτελέσουν έναν υπολογισμό backprop για τον υπολογισμό της κλίσης και τέλος τον υπολογισμό των βαρών και τη βελτιστοποίηση των παραμέτρων με το autograd.

Στο μοντέλο οπτικοποίησης, το εκπαιδευμένο δίκτυο θα δοκιμαστεί με μια παρτίδα εικόνων για την πρόβλεψη των ετικετών. Στη συνέχεια θα οπτικοποιηθεί με τη βοήθεια του matplotlib.

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

visualize_model(vgg_based)

plt.show()

Βήμα 4) Αποτελέσματα

Το τελικό αποτέλεσμα είναι ότι πετύχατε ακρίβεια 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

Τέλος, η έξοδος του μοντέλου μας θα απεικονιστεί με το matplot παρακάτω:

Οπτικοποιήθηκε με Matplot
Οπτικοποιήθηκε με Matplot

Περίληψη

Λοιπόν, ας τα συνοψίσουμε όλα! Ο πρώτος παράγοντας είναι ότι το PyTorch είναι ένα αναπτυσσόμενο πλαίσιο βαθιάς μάθησης για αρχάριους ή για ερευνητικούς σκοπούς. Προσφέρει υψηλό χρόνο υπολογισμού, δυναμικό γράφημα, υποστήριξη GPU και είναι πλήρως γραμμένο Python. Μπορείτε να ορίσετε τη δική σας μονάδα δικτύου με ευκολία και να κάνετε τη διαδικασία εκπαίδευσης με μια εύκολη επανάληψη. Είναι ξεκάθαρο ότι το PyTorch είναι ιδανικό για αρχάριους να ανακαλύψουν βαθιά μάθηση και για επαγγελματίες ερευνητές είναι πολύ χρήσιμο με ταχύτερο χρόνο υπολογισμού και επίσης την πολύ χρήσιμη λειτουργία autograd για να βοηθήσει το δυναμικό γράφημα.