컴퓨터 비전(Vision)을 위한 전이학습(Transfer Learning) — PyTorch Tutorials 1.4.0 documentation
Note Click here to download the full example code 컴퓨터 비전(Vision)을 위한 전이학습(Transfer Learning) Author: Sasank Chilamkurthy번역: 박정환 이 튜토리얼에서는 전이학습(Transfer Learning)을 이용하여 이미지 분류를
tutorials.pytorch.kr
전이학습이란?
- Deep하게 이미 학습된 알고리즘을 pretrained model로 가지고 와서 일무 layer만을 학습하는 방법
- 모델 학습 시간을 파격적으로 줄일 수 있기 때문에 아주 유용
- torchvision에는 ILSVRC 우승 알고리즘을 pretrained 모델로 쓸 수 있는데, 단 한 줄로도 구현 가능함
model_ft = models.resnet18(pretrained=True)
전이학습 시나리오(2가지)
- 합성곱 신경망의 미세조정(finetuning) : 무작위 초기화 대신, 신경망을 ImageNet1000 데이터셋 등으로 미리 학습한 신경망으로 초기화함(학습의 나머지 과정은 일반 신경망과 동일)
- 고정된 특징 추출기로써의 합성곱 신경망 : full-connected 신경망을 제외한 모든 신경망의 가중치를 고정시킴. 마지막 full-connected layer만 무작위로 초기 세팅되어 이 계층만 학습함
# License: BSD
# Author: Sasank Chilamkurthy
from __future__ import print_function, division
import torch
import torch.nn as nn
import torch.optim as optim
from torch.optim import lr_scheduler
import numpy as np
import torchvision
from torchvision import datasets, models, transforms
import matplotlib.pyplot as plt
import time
import os
import copy
plt.ion() # 대화형 모드
데이터 불러오기
- 데이터는 여기 에서 다운로드(작업 디렉토리에 압축 풀기)
- 개미와 벌 분류 문제
# 학습을 위해 데이터 증가(augmentation) 및 일반화(normalization)
# 검증을 위한 일반화
data_transforms = {
'train': transforms.Compose([
transforms.RandomResizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
'val': transforms.Compose([
transforms.Resize(256),
transforms.CenterCrop(224),
transforms.ToTensor(),
transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])
]),
}
data_dir = 'data/hymenoptera_data'
image_datasets = {x: datasets.ImageFolder(os.path.join(data_dir, x),
data_transforms[x])
for x in ['train', 'val']}
dataloaders = {x: torch.utils.data.DataLoader(image_datasets[x], batch_size=4,
shuffle=True, num_workers=4)
for x in ['train', 'val']}
dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'val']}
class_names = image_datasets['train'].classes
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
모델 학습하기
def train_model(model, criterion, optimizer, scheduler, num_epochs=25):
since = time.time()
best_model_wts = copy.deepcopy(model.state_dict())
best_acc = 0.0
for epoch in range(num_epochs):
print('Epoch {}/{}'.format(epoch, num_epochs - 1))
print('-' * 10)
# 각 에폭(epoch)은 학습 단계와 검증 단계를 갖습니다.
for phase in ['train', 'val']:
if phase == 'train':
model.train() # 모델을 학습 모드로 설정
else:
model.eval() # 모델을 평가 모드로 설정
running_loss = 0.0
running_corrects = 0
# 데이터를 반복
for inputs, labels in dataloaders[phase]:
inputs = inputs.to(device)
labels = labels.to(device)
# 매개변수 경사도를 0으로 설정
optimizer.zero_grad()
# 순전파
# 학습 시에만 연산 기록을 추적
with torch.set_grad_enabled(phase == 'train'):
outputs = model(inputs)
_, preds = torch.max(outputs, 1)
loss = criterion(outputs, labels)
# 학습 단계인 경우 역전파 + 최적화
if phase == 'train':
loss.backward()
optimizer.step()
# 통계
running_loss += loss.item() * inputs.size(0)
running_corrects += torch.sum(preds == labels.data)
if phase == 'train':
scheduler.step()
epoch_loss = running_loss / dataset_sizes[phase]
epoch_acc = running_corrects.double() / dataset_sizes[phase]
print('{} Loss: {:.4f} Acc: {:.4f}'.format(
phase, epoch_loss, epoch_acc))
# 모델을 깊은 복사(deep copy)함
if phase == 'val' and epoch_acc > best_acc:
best_acc = epoch_acc
best_model_wts = copy.deepcopy(model.state_dict())
print()
time_elapsed = time.time() - since
print('Training complete in {:.0f}m {:.0f}s'.format(
time_elapsed // 60, time_elapsed % 60))
print('Best val Acc: {:4f}'.format(best_acc))
# 가장 나은 모델 가중치를 불러옴
model.load_state_dict(best_model_wts)
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['val']):
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: {}'.format(class_names[preds[j]]))
imshow(inputs.cpu().data[j])
if images_so_far == num_images:
model.train(mode=was_training)
return
model.train(mode=was_training)
합성곱 신경망 미세조정(finetuning)
- 미리 학습한 모델을 불러온 후 마지막의 완전히 연결된 계층을 초기화
model_ft = models.resnet18(pretrained=True)
num_ftrs = model_ft.fc.in_features
# 여기서 각 출력 샘플의 크기는 2로 설정합니다.(개미, 벌)
# 또는, nn.Linear(num_ftrs, len (class_names))로 일반화할 수 있습니다.
model_ft.fc = nn.Linear(num_ftrs, 2)
model_ft = model_ft.to(device)
criterion = nn.CrossEntropyLoss()
# 모든 매개변수들이 최적화되었는지 관찰
optimizer_ft = optim.SGD(model_ft.parameters(), lr=0.001, momentum=0.9)
# 7 에폭마다 0.1씩 학습율 감소
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_ft, step_size=7, gamma=0.1)
- CPU에서는 15-25분 가량, GPU에서는 1분 이내의 시간소요
model_ft = train_model(model_ft, criterion, optimizer_ft, exp_lr_scheduler, num_epochs=25)
- 예측 결과 일부 확인
visualize_model(model_ft)
고정된 특징 추출기로써의 합성곱 신경망
- 마지막 계층을 제외한 신경망의 모든 부분 고정
- requires_grad == False 로 설정하여 매개변수를 고정 => backward() 중에 경사도가 계산되지 않도록 해야함
model_conv = torchvision.models.resnet18(pretrained=True)
for param in model_conv.parameters():
param.requires_grad = False
# 새로 생성된 모듈의 매개변수는 기본값이 requires_grad=True 임
num_ftrs = model_conv.fc.in_features
model_conv.fc = nn.Linear(num_ftrs, 2)
model_conv = model_conv.to(device)
criterion = nn.CrossEntropyLoss()
# 이전과는 다르게 마지막 계층의 매개변수들만 최적화되는지 관찰
optimizer_conv = optim.SGD(model_conv.fc.parameters(), lr=0.001, momentum=0.9)
# 7 에폭마다 0.1씩 학습율 감소
exp_lr_scheduler = lr_scheduler.StepLR(optimizer_conv, step_size=7, gamma=0.1)
- 대부분의 레이어에서 backward 계산을 생략하므로 시간이 절반정도 걸림(forward는 계산함)
model_conv = train_model(model_conv, criterion, optimizer_conv, exp_lr_scheduler, num_epochs=25)
- 예측 결과 확인
visualize_model(model_conv)
plt.ioff()
plt.show()
'Undergraduate > ML & DL' 카테고리의 다른 글
[winSCP] 서버 사용 시 유용한 프로그램 (0) | 2020.05.20 |
---|---|
[Face Recognition] 얼굴 인식 출입, 어떻게 하는걸까? (0) | 2020.05.20 |
[GPU] 다수의 GPU 중 원하는 GPU 타겟팅하기 (0) | 2020.05.13 |
[PyTorch tutorial] PyTorch에서 GPU 활용하기 (0) | 2020.05.12 |
[PyTorch tutorial] 파이토치로 딥러닝하기 : 60분만에 끝장내기 (0) | 2020.05.12 |