PyTorch Transfer Learning Tutorial med eksempler

Hva er overfรธringslรฆring?

Overfรธr lรฆring er en teknikk for รฅ bruke en trent modell for รฅ lรธse en annen relatert oppgave. Det er en forskningsmetode for maskinlรฆring som lagrer kunnskapen som er oppnรฅdd mens du lรธser et bestemt problem og bruker den samme kunnskapen til รฅ lรธse et annet, men relatert problem. Dette forbedrer effektiviteten ved รฅ gjenbruke informasjonen som er samlet inn fra den tidligere lรฆrte oppgaven.

Det er populรฆrt รฅ bruke andre nettverksmodellvekter for รฅ redusere treningstiden din fordi du trenger mye data for รฅ trene en nettverksmodell. For รฅ redusere treningstiden bruker du andre nettverk og dets vekt og modifiserer det siste laget for รฅ lรธse problemet vรฅrt. Fordelen er at du kan bruke et lite datasett for รฅ trene det siste laget.

Neste i denne PyTorch Transfer learning-veiledning, vi lรฆrer hvordan du bruker Transfer Learning med PyTorch.

Laster inn datasett

Laster inn datasett

Kilde: Alien vs Predator Kaggle

Fรธr du begynner รฅ bruke Transfer Learning PyTorch, mรฅ du forstรฅ datasettet du skal bruke. I denne Transfer Learning PyTorFor eksempel skal du klassifisere en romvesen og en rovdyr fra nesten 700 bilder. For denne teknikken trenger du egentlig ikke en stor mengde data for รฅ trene. Du kan laste ned datasettet fra Kaggle: Alien vs. Predator.

Hvordan bruke overfรธringslรฆring?

Her er en trinnvis prosess for hvordan du bruker Transfer Learning for dyp lรฆring med PyTorch:

Trinn 1) Last inn dataene

Det fรธrste trinnet er รฅ laste inn dataene vรฅre og gjรธre litt transformasjon til bilder slik at de samsvarer med nettverkskravene.

Du vil laste inn dataene fra en mappe med torchvision.dataset. Modulen vil iterere i mappen for รฅ dele dataene for tog og validering. Transformasjonsprosessen vil beskjรฆre bildene fra midten, utfรธre en horisontal flipp, normalisere og til slutt konvertere den til tensor ved hjelp av 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")

La oss visualisere datasettet vรฅrt for PyTorch Overfรธr lรฆring. Visualiseringsprosessen vil hente neste gruppe bilder fra togdatalasterne og etikettene 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 av bilder
Batch av bilder

Trinn 2) Definer modell

I dette Dyp lรฆring prosess, vil du bruke ResNet18 fra torchvision-modulen.

Du skal bruke torchvision.models til รฅ laste inn resnet18 med den forhรฅndstrente vekten satt til True. Etter det fryser du lagene slik at disse lagene ikke kan trenes. Du modifiserer ogsรฅ det siste laget med et lineรฆrt lag som passer vรฅre behov, det vil si 2 klasser. Du bruker ogsรฅ CrossEntropyLoss for en flerklasse-tapfunksjon, og for optimaliseringen bruker du SGD med en lรฆringsrate pรฅ 0.0001 og et momentum pรฅ 0.9, som vist i Py-diagrammet nedenfor.Torch Eksempel pรฅ overfรธringslรฆ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)

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

Trinn 3) Tren og test modell

Vi skal bruke noen av funksjonene fra Transfer Learning PyTorch-opplรฆring for รฅ hjelpe oss med รฅ trene og evaluere modellen vรฅr.

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 overfรธringslรฆringen i PyTorFor eksempel, la oss starte treningsprosessen vรฅr med antall epoker satt til 25 og evaluere etter treningsprosessen. Ved hvert treningstrinn vil modellen ta input og forutsi output. Deretter vil den forutsagte outputen bli sendt til kriteriet for รฅ beregne tapene. Deretter vil tapene utfรธre en backprop-beregning for รฅ beregne gradienten og til slutt beregne vektene og optimalisere parametrene med autograd.

Ved visualiseringsmodellen vil det trente nettverket bli testet med en gruppe bilder for รฅ forutsi etikettene. Deretter vil det bli visualisert ved hjelp av matplotlib.

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

visualize_model(vgg_based)

plt.show()

Trinn 4) Resultater

Sluttresultatet er at du oppnรฅdde en nรธyaktighet 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

Avslutt da vil utdataene til modellen vรฅr bli visualisert med matplott nedenfor:

Visualisert med Matplot
Visualisert med Matplot

Sammendrag

Sรฅ, la oss oppsummere alt! Den fรธrste faktoren er PyTorch er et voksende rammeverk for dyp lรฆring for nybegynnere eller forskningsformรฅl. Det tilbyr hรธy beregningstid, dynamisk graf, GPU-stรธtte og er fullstendig skrevet i ... PythonDu kan enkelt definere din egen nettverksmodul og gjennomfรธre treningsprosessen med en enkel iterasjon. Det er tydelig at PyTorch er ideelt for nybegynnere som vil lรฆre om dyp lรฆring, og for profesjonelle forskere er det veldig nyttig med raskere beregningstid og den svรฆrt nyttige autograd-funksjonen som hjelper med dynamiske grafer.

Oppsummer dette innlegget med: