Hướng dẫn học chuyển giao PyTorch kèm ví dụ

Học chuyển tiếp là gì?

Chuyển giao học tập là một kỹ thuật sử dụng mô hình đã được huấn luyện để giải quyết một nhiệm vụ liên quan khác. Đó là một phương pháp nghiên cứu Machine Learning lưu trữ kiến ​​thức thu được trong khi giải quyết một vấn đề cụ thể và sử dụng kiến ​​thức tương tự để giải quyết một vấn đề khác có liên quan. Điều này cải thiện hiệu quả bằng cách sử dụng lại thông tin thu thập được từ nhiệm vụ đã học trước đó.

Việc sử dụng trọng lượng mô hình mạng khác để giảm thời gian đào tạo là điều phổ biến vì bạn cần nhiều dữ liệu để đào tạo mô hình mạng. Để giảm thời gian đào tạo, bạn sử dụng các mạng khác và trọng lượng của nó, đồng thời sửa đổi lớp cuối cùng để giải quyết vấn đề của chúng ta. Ưu điểm là bạn có thể sử dụng một tập dữ liệu nhỏ để huấn luyện lớp cuối cùng.

Tiếp theo trong hướng dẫn học Chuyển giao PyTorch này, chúng ta sẽ tìm hiểu cách sử dụng Học chuyển giao với PyTorch.

Đang tải tập dữ liệu

Đang tải tập dữ liệu

Nguồn: Alien vs. Predator Kaggle

Trước khi bắt đầu sử dụng Transfer Learning PyTorch, bạn cần hiểu tập dữ liệu mà bạn sắp sử dụng. Trong ví dụ về Transfer Learning PyTorch này, bạn sẽ phân loại Người ngoài hành tinh và Động vật ăn thịt từ gần 700 hình ảnh. Đối với kỹ thuật này, bạn không thực sự cần một lượng lớn dữ liệu để đào tạo. Bạn có thể tải xuống tập dữ liệu từ Kaggle: Người ngoài hành tinh vs. Kẻ săn mồi.

Làm thế nào để sử dụng phương pháp học chuyển tiếp?

Dưới đây là quy trình từng bước về cách sử dụng Transfer Learning cho Deep Learning với PyTorch:

Bước 1) Tải dữ liệu

Bước đầu tiên là tải dữ liệu của chúng tôi và thực hiện một số chuyển đổi thành hình ảnh sao cho phù hợp với yêu cầu của mạng.

Bạn sẽ tải dữ liệu từ một thư mục có torchvision.dataset. Mô-đun sẽ lặp lại trong thư mục để phân chia dữ liệu để đào tạo và xác thực. Quá trình chuyển đổi sẽ cắt hình ảnh từ trung tâm, thực hiện lật ngang, chuẩn hóa và cuối cùng chuyển đổi nó thành tensor bằng 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")

Hãy trực quan hóa tập dữ liệu của chúng tôi về PyTorch Transfer Learning. Quá trình trực quan hóa sẽ lấy lô hình ảnh tiếp theo từ bộ tải dữ liệu và nhãn của tàu rồi hiển thị nó bằng 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()
Hàng loạt hình ảnh
Hàng loạt hình ảnh

Bước 2) Xác định mô hình

Với Học kĩ càng quá trình này, bạn sẽ sử dụng ResNet18 từ mô-đun torchvision.

Bạn sẽ sử dụng torchvision.models để tải resnet18 với trọng số được đào tạo trước được đặt thành True. Sau đó, bạn sẽ đóng băng các lớp để các lớp này không thể huấn luyện được. Bạn cũng sửa đổi lớp cuối cùng bằng một lớp Tuyến tính để phù hợp với nhu cầu của chúng tôi đó là 2 lớp. Bạn cũng sử dụng CrossEntropyLoss cho hàm mất nhiều lớp và đối với trình tối ưu hóa, bạn sẽ sử dụng SGD với tốc độ học là 0.0001 và xung lượng là 0.9 như trong ví dụ Học chuyển giao PyTorch bên dưới.

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

Cấu trúc mô hình đầu ra

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

Bước 3) Đào tạo và thử nghiệm mô hình

Chúng ta sẽ sử dụng một số chức năng từ Transfer Learning Hướng dẫn PyTorch để giúp chúng tôi đào tạo và đánh giá mô hình của mình.

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)

Cuối cùng, trong ví dụ Transfer Learning in PyTorch này, hãy bắt đầu quá trình đào tạo của chúng ta với số kỷ nguyên được đặt thành 25 và đánh giá sau quá trình đào tạo. Ở mỗi bước huấn luyện, mô hình sẽ lấy đầu vào và dự đoán đầu ra. Sau đó, sản lượng dự đoán sẽ được chuyển đến tiêu chí để tính toán tổn thất. Sau đó, tổn thất sẽ thực hiện phép tính backprop để tính gradient và cuối cùng là tính trọng số và tối ưu hóa các tham số bằng autograd.

Ở mô hình trực quan hóa, mạng được đào tạo sẽ được kiểm tra với một loạt hình ảnh để dự đoán nhãn. Sau đó, nó sẽ được hiển thị với sự trợ giúp của matplotlib.

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

visualize_model(vgg_based)

plt.show()

Bước 4) Kết quả

Kết quả cuối cùng là bạn đạt được độ chính xác là 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

Kết thúc thì đầu ra của mô hình của chúng ta sẽ được hiển thị bằng matplot bên dưới:

Trực quan hóa bằng Matplot
Trực quan hóa bằng Matplot

Tổng kết

Vậy, chúng ta hãy tóm tắt mọi thứ! Yếu tố đầu tiên là PyTorch là một khuôn khổ học sâu đang phát triển dành cho người mới bắt đầu hoặc cho mục đích nghiên cứu. Nó cung cấp thời gian tính toán cao, Đồ thị động, hỗ trợ GPU và được viết hoàn toàn bằng Python. Bạn có thể xác định mô-đun mạng của riêng mình một cách dễ dàng và thực hiện quy trình đào tạo một cách dễ dàng. Rõ ràng rằng PyTorch lý tưởng cho những người mới bắt đầu tìm hiểu deep learning và đối với các nhà nghiên cứu chuyên nghiệp, nó rất hữu ích với thời gian tính toán nhanh hơn và chức năng autograd rất hữu ích để hỗ trợ biểu đồ động.