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