Навчальний посібник із передавання PyTorch із прикладами

Що таке трансферне навчання?

Трансферне навчання це техніка використання навченої моделі для вирішення іншого пов’язаного завдання. Це метод дослідження машинного навчання, який зберігає знання, отримані під час вирішення конкретної проблеми, і використовує ті самі знання для вирішення іншої, але пов’язаної проблеми. Це покращує ефективність шляхом повторного використання інформації, зібраної під час виконання попереднього завдання.

Популярно використовувати іншу вагу моделі мережі, щоб скоротити час навчання, оскільки для навчання моделі мережі потрібно багато даних. Щоб скоротити час навчання, ви використовуєте інші мережі та їх вагу та змінюєте останній шар, щоб вирішити нашу проблему. Перевагою є те, що ви можете використовувати невеликий набір даних для навчання останнього рівня.

Далі в цьому підручнику з навчання PyTorch Transfer ми навчимося використовувати Transfer Learning із PyTorch.

Завантаження набору даних

Завантаження набору даних

Джерело: Alien vs. Predator Kaggle

Перш ніж почати використовувати Transfer Learning PyTorch, вам потрібно зрозуміти набір даних, який ви збираєтеся використовувати. У цьому прикладі Transfer Learning PyTorch ви класифікуєте прибульця та хижака з майже 700 зображень. Для навчання цієї методики вам не потрібен великий обсяг даних. Ви можете завантажити набір даних з Kaggle: Чужий проти Хижака.

Як використовувати Transfer Learning?

Ось крок за кроком, як використовувати Transfer Learning для глибокого навчання з PyTorch:

Крок 1) Завантажте дані

Першим кроком є ​​завантаження наших даних і перетворення зображень, щоб вони відповідали вимогам мережі.

Ви завантажите дані з папки torchvision.dataset. Модуль виконуватиме ітерацію в папці, щоб розділити дані для підготовки та перевірки. Процес трансформації обрізає зображення з центру, виконує горизонтальне відображення, нормалізує та, нарешті, перетворює зображення на тензор за допомогою глибокого навчання.

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

Давайте візуалізуємо наш набір даних для PyTorch Transfer Learning. Процес візуалізації отримає наступну партію зображень із завантажувачів даних поїзда та міток і відобразить їх за допомогою 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()
Пакет зображень
Пакет зображень

Крок 2) Визначте модель

В цьому Глибоке навчання ви будете використовувати ResNet18 з модуля torchvision.

Ви будете використовувати torchvision.models для завантаження resnet18 з попередньо навченою вагою, встановленою як True. Після цього ви заморозите шари, щоб ці шари не можна було тренувати. Ви також змінюєте останній шар за допомогою лінійного шару, щоб відповідати нашим потребам, тобто 2 класи. Ви також використовуєте CrossEntropyLoss для багатокласової функції втрат, а для оптимізатора ви використовуєте SGD зі швидкістю навчання 0.0001 і імпульсом 0.9, як показано в наведеному нижче прикладі PyTorch Transfer Learning.

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

Структура вихідної моделі

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) Навчання та тестування моделі

Ми будемо використовувати деякі функції з Transfer Learning Підручник з PyTorch щоб допомогти нам навчити та оцінити нашу модель.

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)

Нарешті, у цьому прикладі Transfer Learning у PyTorch давайте почнемо наш навчальний процес із установленою кількістю епох 25 і оцінимо після процесу навчання. На кожному кроці навчання модель прийматиме вхідні дані та прогнозуватиме результати. Після цього прогнозований вихід буде передано критерію для розрахунку втрат. Потім втрати виконають розрахунок опорної опори для обчислення градієнта та, нарешті, обчислення ваг і оптимізації параметрів за допомогою autograd.

У моделі візуалізації навчену мережу буде перевірено за допомогою пакета зображень, щоб передбачити мітки. Потім він візуалізується за допомогою matplotlib.

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

visualize_model(vgg_based)

plt.show()

Крок 4) Результати

Кінцевий результат полягає в тому, що ви досягли точності 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

Після цього результат нашої моделі буде візуалізовано за допомогою matplot нижче:

Візуалізовано за допомогою Matplot
Візуалізовано за допомогою Matplot

Підсумки

Отже, підсумовуємо все! Перший фактор: PyTorch — це платформа глибокого навчання, що розвивається, для початківців або для дослідницьких цілей. Він пропонує великий час обчислень, Dynamic Graph, підтримку графічних процесорів і повністю написаний Python. Ви можете легко визначити свій власний мережевий модуль і виконати процес навчання за допомогою легкої ітерації. Зрозуміло, що PyTorch ідеально підходить для початківців, щоб дізнатися про глибоке навчання, а для професійних дослідників він дуже корисний завдяки швидшому часу обчислень, а також дуже корисній функції автоградації для підтримки динамічного графіка.