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 learning tutorial, vi lรฆrer, hvordan man bruger Transfer Learning med PyTorch.

Indlรฆser datasรฆt

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 denne Transfer Learning PyTorFor eksempel skal du klassificere en Alien og en Predator ud fra nรฆsten 700 billeder. Til denne teknik behรธver du ikke rigtig en stor mรฆngde data at trรฆne. Du kan downloade datasรฆttet fra Kaggle: Alien vs. Predator.

Hvordan bruger man Transfer Learning?

Her er en trin-for-trin proces til, hvordan man 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 for PyTorch Transfer Learning. Visualiseringsprocessen vil hente den nรฆste batch af billeder fra togets dataindlรฆsere og etiketter og vise dem 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()
Batch af billeder
Batch af billeder

Trin 2) Definer model

I denne Deep Learning proces, vil du bruge ResNet18 fra torchvision-modulet.

Du skal bruge torchvision.models til at indlรฆse resnet18 med den forudtrรฆnede vรฆgt sat til True. Derefter fryser du 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 en multiklasse-tabsfunktion, og til optimeringsvรฆrktรธjet bruger du SGD med en lรฆringsrate pรฅ 0.0001 og et momentum pรฅ 0.9, som vist i Py-diagrammet nedenfor.Torch Eksempel pรฅ transferlรฆring.

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

Endelig i denne Transfer Learning i PyTorFor 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 outputtet. Derefter vil det forudsagte output blive sendt til kriteriet for at beregne tabene. Derefter vil tabene udfรธre en backprop-beregning for at beregne gradienten og endelig 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:

Visualiseret med Matplot
Visualiseret med Matplot

Resumรฉ

Sรฅ lad os opsummere det hele! Den fรธrste faktor er PyTorch er et voksende deep learning-framework for begyndere eller forskningsformรฅl. Det tilbyder hรธj beregningstid, dynamisk graf, GPU-understรธttelse og er fuldstรฆndig skrevet i ... PythonDu kan nemt definere dit eget netvรฆrksmodul og udfรธre trรฆningsprocessen med en nem iteration. Det er tydeligt, at PyTorch er ideelt for begyndere, der รธnsker at lรฆre deep learning, og for professionelle forskere er det meget nyttigt med hurtigere beregningstid og den meget nyttige autograd-funktion, der understรธtter dynamiske grafer.

Opsummer dette indlรฆg med: