이미 학습된 잘 알려진 모델을 이용하여 꽃의 종류를 예측하는 예제입니다.
기존의 Minst 예제와는 거의 차이점이 없습니다. 단지 2가지만 다를 뿐입니다.
pytorch의 imageFolder라는 dataset클래스를 사용하였습니다.
traindir = './flower_photos' batch_size = 8 train_loader = torch.utils.data.DataLoader( datasets.ImageFolder(traindir, transforms.Compose([ transforms.RandomSizedCrop(224), transforms.RandomHorizontalFlip(), transforms.ToTensor(), normalize,])), batch_size=batch_size, shuffle=True)
Microsoft에서 발표한 resnet152를 사용합니다.
model = torchvision.models.resnet152(pretrained=True)
새로운 Network로 재구성합니다.
### don't update model parameters
for param in model.parameters() :
param.requires_grad = False
#modify last fully connected layter
model.fc = nn.Linear(model.fc.in_features, cls_num)
일단, 밑의 명령어를 수행시켜서, 실행디렉토리 밑에 꽃 이미지 압축파일을 풀어 놓습니다.
In [1]:
!if [ ! -d "/tmp/flower_photos" ]; then curl http://download.tensorflow.org/example_images/flower_photos.tgz | tar xz -C /tmp ;rm /tmp/flower_photos/LICENSE.txt; fi
In [2]:
%matplotlib inline
In [3]:
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision
from torchvision import datasets, transforms
from torch.autograd import Variable
import matplotlib.pyplot as plt
import numpy as np
is_cuda = torch.cuda.is_available() # cuda 사용가능시, True
traindir = '/tmp/flower_photos'
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
batch_size = 256
train_loader = torch.utils.data.DataLoader(
datasets.ImageFolder(traindir,
transforms.Compose([
transforms.RandomSizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,])),
batch_size=batch_size,
shuffle=True,
num_workers=4)
cls_num = len(datasets.folder.find_classes(traindir)[0])
test_loader = torch.utils.data.DataLoader(
datasets.ImageFolder(traindir,
transforms.Compose([
transforms.RandomSizedCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
normalize,])),
batch_size=batch_size,
shuffle=True,
num_workers=1)
In [4]:
model = torchvision.models.resnet152(pretrained = True)
### don't update model parameters
for param in model.parameters() :
param.requires_grad = False
#modify last fully connected layter
model.fc = nn.Linear(model.fc.in_features, cls_num)
fc_parameters = [
{'params': model.fc.parameters()},
]
optimizer = torch.optim.Adam(fc_parameters, lr=1e-4, weight_decay=1e-4)
loss_fn = nn.CrossEntropyLoss()
if is_cuda : model.cuda(), loss_fn.cuda()
In [5]:
# trainning
model.train()
train_loss = []
train_accu = []
i = 0
for epoch in range(35):
for image, target in train_loader:
image, target = Variable(image.float()), Variable(target) # 입력image Target 설정
if is_cuda : image, target = image.cuda(), target.cuda()
output = model(image) # model 생성
loss = loss_fn(output, target) #loss 생성
optimizer.zero_grad() # zero_grad
loss.backward() # calc backward grad
optimizer.step() # update parameter
pred = output.data.max(1)[1]
accuracy = pred.eq(target.data).sum()/batch_size
train_loss.append(loss.data[0])
train_accu.append(accuracy)
if i % 300 == 0:
print(i, loss.data[0])
i += 1
In [6]:
plt.plot(train_accu)
Out[6]:
In [7]:
plt.plot(train_loss)
Out[7]:
In [8]:
model.eval()
correct = 0
for image, target in test_loader:
if is_cuda : image, target = image.cuda(), target.cuda()
image, target = Variable(image, volatile=True), Variable(target)
output = model(image)
prediction = output.data.max(1)[1]
correct += prediction.eq(target.data).sum()
print('\nTest set: Accuracy: {:.2f}%'.format(100. * correct / len(test_loader.dataset)))