예제가 포함된 PyTorch 전이 학습 튜토리얼

전이 학습이란 무엇입니까?

전학 학습 훈련된 모델을 사용하여 다른 관련 작업을 해결하는 기술입니다. 특정 문제를 해결하면서 얻은 지식을 저장하고, 동일한 지식을 사용하여 다르지만 관련된 또 다른 문제를 해결하는 머신러닝 연구 방법입니다. 이는 이전에 학습한 작업에서 수집된 정보를 재사용하여 효율성을 향상시킵니다.

네트워크 모델을 훈련하려면 많은 데이터가 필요하기 때문에 훈련 시간을 줄이기 위해 다른 네트워크 모델 가중치를 사용하는 것이 일반적입니다. 훈련 시간을 줄이기 위해 다른 네트워크와 그 가중치를 사용하고 마지막 레이어를 수정하여 문제를 해결합니다. 장점은 작은 데이터 세트를 사용하여 마지막 레이어를 훈련할 수 있다는 것입니다.

다음으로 이 PyTorch 전이 학습 튜토리얼에서는 PyTorch에서 전이 학습을 사용하는 방법을 알아봅니다.

데이터 세트 로드 중

데이터 세트 로드 중

출처: Alien vs. Predator Kaggle

Transfer Learning PyTorch를 사용하기 전에 사용할 데이터세트를 이해해야 합니다. 이 전이 학습 PyTorch 예제에서는 거의 700개의 이미지에서 외계인과 프레데터를 분류합니다. 이 기술의 경우 훈련하는 데 실제로 많은 양의 데이터가 필요하지 않습니다. 다음에서 데이터세트를 다운로드할 수 있습니다. Kaggle: 외계인 대 프레데터.

전이 학습을 사용하는 방법은 무엇입니까?

다음은 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단계) 모델 정의

이번에 깊은 학습 프로세스에서는 torchvision 모듈의 ResNet18을 사용하게 됩니다.

torchvision.models를 사용하여 사전 학습된 가중치를 True로 설정하여 resnet18을 로드합니다. 그런 다음 레이어를 동결하여 이러한 레이어가 학습되지 않도록 합니다. 또한 마지막 레이어를 선형 레이어로 수정하여 2개 클래스라는 요구 사항에 맞춥니다. 또한 다중 클래스 손실 함수에 CrossEntropyLoss를 사용하고 최적화 도구에 아래 PyTorch Transfer Learning 예제에서 볼 수 있듯이 학습률이 0.0001이고 모멘텀이 0.9인 SGD를 사용합니다.

## 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의 일부 기능을 사용하겠습니다. 파이토치 튜토리얼 모델을 훈련하고 평가하는 데 도움이 됩니다.

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)

마지막으로 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가 초보자 또는 연구 목적을 위한 성장하는 딥 러닝 프레임워크라는 것입니다. 높은 계산 시간, 동적 그래프, GPU 지원을 제공하며 완전히 작성되었습니다. Python. 자신만의 네트워크 모듈을 쉽게 정의하고 쉬운 반복으로 교육 프로세스를 수행할 수 있습니다. PyTorch는 초보자가 딥 러닝을 배우는 데 이상적이며 전문 연구자들에게는 더 빠른 계산 시간과 동적 그래프를 지원하는 매우 유용한 autograd 기능으로 매우 유용합니다.