PyTorch átviteli tanulási oktatóanyag példákkal

Mi az a transzfertanulás?

Transzfer tanulás egy betanított modell használatával egy másik kapcsolódó feladat megoldására szolgáló technika. Ez egy gépi tanulási kutatási módszer, amely egy adott probléma megoldása során megszerzett tudást tárolja, és ugyanazt a tudást egy másik, de mégis kapcsolódó probléma megoldására használja fel. Ez javítja a hatékonyságot azáltal, hogy újra felhasználja a korábban tanult feladatból összegyűjtött információkat.

Népszerű más hálózati modell súlyok használata az edzési idő csökkentésére, mivel sok adatra van szüksége a hálózati modell betanításához. Az edzési idő csökkentése érdekében más hálózatokat és azok súlyát használjuk, és módosítjuk az utolsó réteget a probléma megoldásához. Az előnye, hogy egy kis adatkészletet használhat az utolsó réteg betanításához.

A PyTorch Transfer tanulási oktatóanyag következő részében megtudjuk, hogyan kell használni a Transfer Learninget a PyTorch segítségével.

Adatkészlet betöltése

Adatkészlet betöltése

Forrás: Alien vs. Predator Kaggle

A Transfer Learning PyTorch használatának megkezdése előtt meg kell értenie a használni kívánt adatkészletet. Ebben a Transfer Learning PyTorch példában közel 700 képből osztályoz egy Alient és egy Predatort. Ehhez a technikához nincs szükség nagy mennyiségű adatra a betanításhoz. Az adatkészletet innen töltheti le Kaggle: Alien vs. Predator.

Hogyan használjuk a transzfertanulást?

Íme egy lépésről lépésre bemutatott folyamat a Transfer Learning for Deep Learning használatához a PyTorch segítségével:

1. lépés) Töltse be az adatokat

Az első lépés az adataink betöltése, és a képek átalakítása, hogy azok megfeleljenek a hálózati követelményeknek.

Az adatokat egy torchvision.dataset mappából fogja betölteni. A modul a mappában iterálva felosztja az adatokat a vonatozáshoz és az érvényesítéshez. Az átalakítási folyamat a képeket középről levágja, vízszintes átfordítást hajt végre, normalizálja, végül pedig tenzorrá konvertálja a Deep Learning segítségével.

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

Vizualizáljuk a PyTorch Transfer Learning adatkészletünket. A vizualizációs folyamat megkapja a következő képköteget a vonat adatbetöltőitől és címkéitől, és megjeleníti azt matplottal.

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()
Képek köteg
Képek köteg

2. lépés) Határozza meg a modellt

Ebben Deep Learning folyamat, akkor a ResNet18-at fogja használni a torchvision modulból.

A torchvision.models segítségével töltse be a resnet18 fájlt, az előre betanított súly True értékre állítva. Ezt követően lefagyasztja a rétegeket, így ezek a rétegek nem képezhetők. Az utolsó réteget egy Lineáris réteggel is módosíthatja, hogy megfeleljen az igényeinknek, ami 2 osztály. Használja a CrossEntropyLoss-t a többosztályú veszteségfüggvényhez, az optimalizálóhoz pedig az SGD-t 0.0001 tanulási sebességgel és 0.9-es lendülettel, amint az az alábbi PyTorch Transfer Learning példában látható.

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

A kimeneti modell szerkezete

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

3. lépés) Betanítás és modell tesztelése

A Transfer Learning néhány funkcióját fogjuk használni PyTorch oktatóanyag hogy segítsen a modellünk képzésében és értékelésében.

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)

Végül ebben a PyTorch átviteli tanulási példában kezdjük a képzési folyamatot 25-re beállított korszakok számával, és értékeljük a betanítási folyamat után. Minden képzési lépésnél a modell veszi a bemenetet és megjósolja a kimenetet. Ezt követően a várható teljesítményt átadjuk a kritériumnak a veszteségek kiszámításához. Ezután a veszteségek egy backprop számítást végeznek a gradiens kiszámításához, végül a súlyok kiszámításához és a paraméterek optimalizálásához az autograd segítségével.

A vizualizációs modellnél a képzett hálózatot egy köteg képpel tesztelik a címkék előrejelzése érdekében. Ezután a matplotlib segítségével láthatóvá válik.

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

visualize_model(vgg_based)

plt.show()

4. lépés: Eredmények

A végeredmény az, hogy 92%-os pontosságot ért el.

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

Vége, majd a modellünk kimenete az alábbi matplot segítségével jelenik meg:

Matplottal vizualizálva
Matplottal vizualizálva

Összegzésként

Szóval, foglaljunk össze mindent! Az első tényező az, hogy a PyTorch egy növekvő mély tanulási keretrendszer kezdőknek vagy kutatási célokra. Magas számítási időt, dinamikus grafikont, GPU támogatást kínál, és teljesen be van írva Python. Könnyedén definiálhatja saját hálózati modulját, és egyszerű iterációval elvégezheti a betanítási folyamatot. Nyilvánvaló, hogy a PyTorch ideális kezdőknek a mély tanuláshoz, és a professzionális kutatók számára nagyon hasznos a gyorsabb számítási idővel, valamint a dinamikus grafikonok segítésére szolgáló nagyon hasznos autograd funkcióval.

Foglald össze ezt a bejegyzést a következőképpen: