PyTorch Transfer Learning Tutorial mit Beispielen
Was ist Transferlernen?
Lernen übertragen ist eine Technik, bei der ein trainiertes Modell verwendet wird, um eine andere verwandte Aufgabe zu lösen. Es handelt sich um eine Forschungsmethode des maschinellen Lernens, die das bei der Lösung eines bestimmten Problems gewonnene Wissen speichert und dasselbe Wissen zur Lösung eines anderen, aber verwandten Problems verwendet. Dies verbessert die Effizienz, indem die aus der zuvor erlernten Aufgabe gesammelten Informationen wiederverwendet werden.
Es ist beliebt, eine andere Netzwerkmodellgewichtung zu verwenden, um die Trainingszeit zu verkürzen, da Sie zum Trainieren eines Netzwerkmodells viele Daten benötigen. Um die Trainingszeit zu verkürzen, nutzen Sie andere Netzwerke und deren Gewicht und modifizieren die letzte Schicht, um unser Problem zu lösen. Der Vorteil besteht darin, dass Sie einen kleinen Datensatz verwenden können, um die letzte Ebene zu trainieren.
Als nächstes lernen wir in diesem PyTorch Transfer-Lerntutorial, wie man Transfer Learning mit PyTorch verwendet.
Datensatz laden
Quelle: Alien vs. Predator Kaggle
Bevor Sie Transfer Learning PyTorch verwenden, müssen Sie den Datensatz verstehen, den Sie verwenden möchten. In diesem Transfer Learning PyTorch-Beispiel klassifizieren Sie einen Außerirdischen und einen Raubtier aus fast 700 Bildern. Für diese Technik benötigen Sie nicht unbedingt eine große Datenmenge zum Trainieren. Sie können den Datensatz herunterladen unter Kaggle: Alien vs. Predator.
Wie nutzt man Transferlernen?
Hier ist ein Schritt-für-Schritt-Prozess zur Verwendung von Transfer Learning für Deep Learning mit PyTorch:
Schritt 1) Laden Sie die Daten
Der erste Schritt besteht darin, unsere Daten zu laden und die Bilder so umzuwandeln, dass sie den Netzwerkanforderungen entsprechen.
Sie laden die Daten aus einem Ordner mit Torchvision.dataset. Das Modul durchläuft den Ordner, um die Daten für Training und Validierung aufzuteilen. Der Transformationsprozess schneidet die Bilder von der Mitte aus zu, führt eine horizontale Spiegelung durch, normalisiert sie und wandelt sie schließlich mithilfe von Deep Learning in einen Tensor um.
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")
Lassen Sie uns unseren Datensatz für PyTorch Transfer Learning visualisieren. Der Visualisierungsprozess ruft den nächsten Bilderstapel von den Zugdatenladern und Etiketten ab und zeigt ihn mit Matplot an.
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()
Schritt 2) Modell definieren
In diesem Tiefes Lernen Im Prozess verwenden Sie ResNet18 aus dem Torchvision-Modul.
Sie verwenden torchvision.models, um resnet18 mit dem vorab trainierten Gewicht auf True zu laden. Danach frieren Sie die Schichten ein, damit diese Schichten nicht trainiert werden können. Sie ändern auch die letzte Schicht mit einer linearen Schicht, um sie unseren Anforderungen anzupassen, d. h. mit 2 Klassen. Sie verwenden auch CrossEntropyLoss für die Verlustfunktion mehrerer Klassen und für den Optimierer verwenden Sie SGD mit einer Lernrate von 0.0001 und einem Momentum von 0.9, wie im folgenden PyTorch Transfer Learning-Beispiel gezeigt.
## 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)
Die Struktur des Ausgabemodells
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) ) )
Schritt 3) Modell trainieren und testen
Wir werden einige der Funktionen von Transfer Learning nutzen PyTorch-Tutorial um uns beim Trainieren und Bewerten unseres Modells zu helfen.
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)
Abschließend beginnen wir in diesem Beispiel zum Transferlernen in PyTorch unseren Trainingsprozess mit einer auf 25 eingestellten Anzahl von Epochen und werten ihn nach dem Trainingsprozess aus. Bei jedem Trainingsschritt übernimmt das Modell die Eingabe und prognostiziert die Ausgabe. Danach wird die vorhergesagte Leistung an das Kriterium zur Berechnung der Verluste übergeben. Anschließend führen die Verluste eine Backprop-Berechnung durch, um den Gradienten zu berechnen und schließlich die Gewichte zu berechnen und die Parameter mit Autograd zu optimieren.
Beim Visualisierungsmodell wird das trainierte Netzwerk mit einer Reihe von Bildern getestet, um die Beschriftungen vorherzusagen. Anschließend wird es mit Hilfe von Matplotlib visualisiert.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
Schritt 4) Ergebnisse
Das Endergebnis ist, dass Sie eine Genauigkeit von 92 % erreicht haben.
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
Am Ende wird die Ausgabe unseres Modells mit Matplot unten visualisiert:
Zusammenfassung
Fassen wir also alles zusammen! Der erste Faktor ist, dass PyTorch ein wachsendes Deep-Learning-Framework für Anfänger oder für Forschungszwecke ist. Es bietet hohe Rechenzeiten, dynamische Graphen, GPU-Unterstützung und ist vollständig in Python. Sie können ganz einfach Ihr eigenes Netzwerkmodul definieren und den Trainingsprozess mit einer einfachen Iteration durchführen. Es ist klar, dass PyTorch ideal für Anfänger zum Erlernen von Deep Learning ist und für professionelle Forscher mit schnellerer Rechenzeit und der sehr hilfreichen Autograd-Funktion zur Unterstützung dynamischer Diagramme sehr nützlich ist.