PyTorch Transfer Learning Tutorial med eksempler
Hvad er Transfer Learning?
Overfør læring er en teknik til at bruge en trænet model til at løse en anden relateret opgave. Det er en Machine Learning-forskningsmetode, der gemmer den opnåede viden, mens du løser et bestemt problem, og bruger den samme viden til at løse et andet andet, men relateret problem. Dette forbedrer effektiviteten ved at genbruge informationen indsamlet fra den tidligere lærte opgave.
Det er populært at bruge andre netværksmodelvægte til at reducere din træningstid, fordi du har brug for en masse data for at træne en netværksmodel. For at reducere træningstiden bruger du andre netværk og dets vægt og ændrer det sidste lag for at løse vores problem. Fordelen er, at du kan bruge et lille datasæt til at træne det sidste lag.
Næste i denne PyTorch Transfer-læringsvejledning lærer vi, hvordan du bruger Transfer Learning med PyTorch.
Indlæser datasæt
Kilde: Alien vs Predator Kaggle
Før du begynder at bruge Transfer Learning PyTorch, skal du forstå det datasæt, du skal bruge. I dette Transfer Learning PyTorch-eksempel vil du klassificere en Alien og en Predator fra næsten 700 billeder. Til denne teknik behøver du egentlig ikke en stor mængde data for at træne. Du kan downloade datasættet fra Kaggle: Alien vs. Predator.
Hvordan bruger man Transfer Learning?
Her er en trinvis proces om, hvordan du bruger Transfer Learning til Deep Learning med PyTorch:
Trin 1) Indlæs dataene
Det første skridt er at indlæse vores data og lave nogle transformationer til billeder, så de matcher netværkskravene.
Du vil indlæse data fra en mappe med torchvision.dataset. Modulet vil iterere i mappen for at opdele dataene til tog og validering. Transformationsprocessen vil beskære billederne fra midten, udføre en vandret vending, normalisere og til sidst konvertere dem til tensor ved hjælp af 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")
Lad os visualisere vores datasæt til PyTorch Transfer Learning. Visualiseringsprocessen vil hente det næste parti billeder fra togdataindlæserne og etiketter og vise det med 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()
Trin 2) Definer model
I denne Deep Learning proces, vil du bruge ResNet18 fra torchvision-modulet.
Du vil bruge torchvision.models til at indlæse resnet18 med den forudtrænede vægt indstillet til at være True. Derefter vil du fryse lagene, så disse lag ikke kan trænes. Du ændrer også det sidste lag med et lineært lag, så det passer til vores behov, dvs. 2 klasser. Du bruger også CrossEntropyLoss til multi-class tab-funktion og til optimizeren vil du bruge SGD med indlæringshastigheden på 0.0001 og et momentum på 0.9 som vist i nedenstående PyTorch Transfer Learning-eksempel.
## 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)
Outputmodellens struktur
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) ) )
Trin 3) Træn og test model
Vi vil bruge nogle af funktionerne fra Transfer Learning PyTorch tutorial at hjælpe os med at træne og evaluere vores model.
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)
Til sidst i dette Transfer Learning i PyTorch eksempel, lad os starte vores træningsproces med antallet af epoker sat til 25 og evaluere efter træningsprocessen. Ved hvert træningstrin vil modellen tage input og forudsige output. Derefter vil det forudsagte output blive overført til kriteriet for at beregne tabene. Derefter vil tabene udføre en backprop-beregning for at beregne gradienten og til sidst beregne vægtene og optimere parametrene med autograd.
Ved visualiseringsmodellen vil det trænede netværk blive testet med en batch af billeder for at forudsige etiketterne. Derefter vil det blive visualiseret ved hjælp af matplotlib.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
Trin 4) Resultater
Det endelige resultat er, at du opnåede en nøjagtighed på 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
Slut så vil output fra vores model blive visualiseret med matplot nedenfor:
Resumé
Så lad os opsummere alt! Den første faktor er PyTorch er en voksende dyb læringsramme for begyndere eller til forskningsformål. Det tilbyder høj beregningstid, Dynamic Graph, GPU'er-understøttelse og det er fuldstændig skrevet ind Python. Du er i stand til at definere dit eget netværksmodul med lethed og udføre træningsprocessen med en nem iteration. Det er klart, at PyTorch er ideel for begyndere til at finde ud af dyb læring, og for professionelle forskere er det meget nyttigt med hurtigere beregningstid og også den meget nyttige autograd-funktion til at hjælpe dynamisk graf.