Minist 예제를 살펴봅시다. 사실 minist 예제는 3장 다룬 기초적인 Neural Networw와 거의 동일 합니다.
단지, 입력 DataLoader를 사용하여 Minist dataset를 이용하는 부분만 차이가 나고, 데이터량이 많아서 시간이 좀 많이 걸리는 부분입니다.
입력 DataLoader를 이용하는 것은 4장에서 잠시 다루었기 때문에, 시간을 줄이기 위해서 cuda gpu를 사용하는 부분을 추가했습니다.
입력변수와 network상의 변수의 torch.Tensor를 cuda() 함수를 통해서 선언하면 됩니다.
is_cuda = torch.cuda.is_available()
if is_cuda : model.cuda()
if is_cuda : data, target = data.cuda(), target.cuda()
In [1]:
%matplotlib inline
In [2]:
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
batch_size = 50
train_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=True, download=True, transform=transforms.ToTensor()),
batch_size=batch_size, shuffle=True)
test_loader = torch.utils.data.DataLoader(
datasets.MNIST('data', train=True, transform=transforms.ToTensor()),
batch_size=1000)
In [3]:
class MnistModel(nn.Module):
def __init__(self):
super(MnistModel, self).__init__()
# input is 28x28
# padding=2 for same padding
self.conv1 = nn.Conv2d(1, 32, 5, padding=2)
# feature map size is 14*14 by pooling
# padding=2 for same padding
self.conv2 = nn.Conv2d(32, 64, 5, padding=2)
# feature map size is 7*7 by pooling
self.fc1 = nn.Linear(64*7*7, 1024)
self.fc2 = nn.Linear(1024, 10)
def forward(self, x):
x = F.max_pool2d(F.relu(self.conv1(x)), 2)
x = F.max_pool2d(F.relu(self.conv2(x)), 2)
x = x.view(-1, 64*7*7) # reshape Variable
x = F.relu(self.fc1(x))
x = F.dropout(x, training=self.training)
x = self.fc2(x)
return F.log_softmax(x)
model = MnistModel()
if is_cuda : model.cuda()
loss_fn = nn.NLLLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.0001)
* (입력 생성)
* model 생성
* loss 생성
* zeroGrad
* backpropagation
* optimizer step (update model parameter)
간단하게 loss와 accuracy를 list에 추가하도록 나중에 matplotlib를 이용하여 출력하겠습니다. 이 부분은 train_loss, train_accu라는 list에 loss와 accuracy를 append하면 됩니다. 물론 Tensorboard같은 별도의 전용 tool이 있으면 편리하겠지만, 간단히 확인할 경우 큰 불편사항은 없습니다.
일단 빈 list를 선언한 다음,
train_loss = []
train_accu = []
train과정이나 test과정에 loss와 accuracy를 추가하면 됩니다.
pred = output.data.max(1)[1]
accuracy = pred.eq(target.data).sum()/batch_size
train_loss.append(loss.data[0])
train_accu.append(accuracy)
In [4]:
# trainning
model.train()
train_loss = []
train_accu = []
for epoch in range(3):
for i, (image, target) in enumerate(train_loader):
if is_cuda : image, target = image.cuda(), target.cuda()
image, target = Variable(image), Variable(target) # 입력image Target 설정
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])
In [5]:
plt.plot(train_accu)
Out[5]:
In [6]:
plt.plot(train_loss)
Out[6]:
In [7]:
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)))
In [8]:
checkpoint_filename = 'minist.ckpt'
torch.save(model.state_dict(), checkpoint_filename)
In [9]:
model.eval()
image, target = iter(test_loader).next() #test_loader로 부터 한번만 dataset을 호출
if is_cuda : image, target = image.cuda(), target.cuda()
image, target = Variable(image, volatile=True), Variable(target)
output = model(image)
## 이미지, 참값, 예측값을 numpy array로 변환
images = image.data.cpu().numpy()
cls_true = target.data.cpu().numpy().squeeze()
prediction = output.data.max(1)[1].cpu().numpy().squeeze()
# 예측값이 참값과 틀린것을 확인
incorrect = (prediction != cls_true)
# 예측이 틀린 것만을 추출
images = images[incorrect]
cls_true = cls_true[incorrect]
prediction = prediction[incorrect]
# 에러율을 표지
print('error : {:.1%}, number ={:}'.format(incorrect.sum()/len(incorrect), incorrect.sum()))
# 틀린 것들의 이미지를 표시
tensorImg = torch.Tensor(images)
plt.imshow(torchvision.utils.make_grid(tensorImg).numpy().transpose((1,2,0)))
plt.show()
# 틀린 것들의 예측치를 표시
print('prediction :')
pred_resized = np.pad(prediction, (0, 8 - len(prediction)%8), 'constant', constant_values=(0, 0))
print(pred_resized.reshape(-1,8))
print('\n')
# 틀린 것들의 참값을 표시
print('True :')
true_resized = np.pad(cls_true, (0, 8 - len(cls_true)%8), 'constant', constant_values=(0, 0))
print(true_resized.reshape(-1,8))
In [ ]: