PyTorch Transfer Learning Tutorial med exempel

Vad är Transfer Learning?

Överför lärande är en teknik för att använda en tränad modell för att lösa en annan relaterad uppgift. Det är en forskningsmetod för maskininlärning som lagrar den kunskap som erhållits när man löser ett visst problem och använder samma kunskap för att lösa ett annat annat men relaterat problem. Detta förbättrar effektiviteten genom att återanvända informationen från den tidigare inlärda uppgiften.

Det är populärt att använda andra nätverksmodeller för att minska din träningstid eftersom du behöver mycket data för att träna en nätverksmodell. För att minska träningstiden använder du andra nätverk och dess vikt och modifierar det sista lagret för att lösa vårt problem. Fördelen är att du kan använda en liten datauppsättning för att träna det sista lagret.

Härnäst i denna PyTorch Transfer-inlärningshandledning kommer vi att lära oss hur man använder Transfer Learning med PyTorch.

Laddar datauppsättning

Laddar datauppsättning

Källa: Alien vs Predator Kaggle

Innan du börjar använda Transfer Learning PyTorch måste du förstå datasetet som du ska använda. I det här Transfer Learning PyTorch-exemplet kommer du att klassificera en Alien och en Predator från nästan 700 bilder. För den här tekniken behöver du egentligen inte en stor mängd data för att träna. Du kan ladda ner datamängden från Kaggle: Alien vs. Predator.

Hur använder man Transfer Learning?

Här är en steg-för-steg-process om hur du använder Transfer Learning för djupinlärning med PyTorch:

Steg 1) Ladda data

Det första steget är att ladda vår data och göra lite omvandling till bilder så att de matchar nätverkskraven.

Du kommer att ladda data från en mapp med torchvision.dataset. Modulen kommer att iterera i mappen för att dela upp data för tåg och validering. Transformationsprocessen kommer att beskära bilderna från mitten, utföra en horisontell vändning, normalisera och slutligen konvertera den till tensor med hjälp 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")

Låt oss visualisera vår datauppsättning för PyTorch Transfer Learning. Visualiseringsprocessen kommer att hämta nästa sats bilder från tågdataladdare och etiketter och visa den 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()
Parti bilder
Parti bilder

Steg 2) Definiera modell

I detta Deep Learning process kommer du att använda ResNet18 från torchvision-modulen.

Du kommer att använda torchvision.models för att ladda resnet18 med den förtränade vikten inställd på True. Efter det kommer du att frysa lagren så att dessa lager inte går att träna. Du modifierar även det sista lagret med ett linjärt lager för att passa våra behov som är 2 klasser. Du använder också CrossEntropyLoss för multi-class förlustfunktion och för optimeraren kommer du att använda SGD med inlärningshastigheten 0.0001 och ett momentum på 0.9 som visas i nedanstående PyTorch Transfer Learning-exempel.

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

Utgångsmodellens 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)
  )
)

Steg 3) Träna och testa modell

Vi kommer att använda några av funktionerna från Transfer Learning PyTorch handledning för att hjälpa oss att träna och utvärdera vår modell.

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)

Slutligen i detta Transfer Learning i PyTorch-exemplet, låt oss börja vår träningsprocess med antalet epoker inställt på 25 och utvärdera efter träningsprocessen. Vid varje träningssteg kommer modellen att ta indata och förutsäga resultatet. Efter det kommer den förutsagda uteffekten att överföras till kriteriet för att beräkna förlusterna. Sedan kommer förlusterna att utföra en backprop-beräkning för att beräkna gradienten och slutligen beräkna vikterna och optimera parametrarna med autograd.

Vid visualiseringsmodellen kommer det utbildade nätverket att testas med en grupp bilder för att förutsäga etiketterna. Sedan kommer det att visualiseras med hjälp av matplotlib.

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

visualize_model(vgg_based)

plt.show()

Steg 4) Resultat

Slutresultatet är att du uppnådde en noggrannhet 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

Sluta då kommer produktionen av vår modell att visualiseras med matplot nedan:

Visualiseras med Matplot
Visualiseras med Matplot

Sammanfattning

Så låt oss sammanfatta allt! Den första faktorn är PyTorch är ett växande ramverk för djupinlärning för nybörjare eller för forskningsändamål. Den erbjuder hög beräkningstid, Dynamic Graph, GPU-stöd och det är helt inskrivet Python. Du kan enkelt definiera din egen nätverksmodul och göra träningsprocessen med en enkel iteration. Det är tydligt att PyTorch är idealiskt för nybörjare för att ta reda på djup inlärning och för professionella forskare är det mycket användbart med snabbare beräkningstid och även den mycket hjälpsamma autogradfunktionen för att hjälpa dynamisk graf.

Dagligt Guru99-nyhetsbrev

Kickstarta dagen med de senaste och viktigaste AI-nyheterna som levereras just nu.