<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 Minist 예제
Minist 예제를 살펴봅시다. 사실 minist 예제는 3장 다룬 기초적인 Neural Networw와 거의 동일 합니다.   
단지, 입력 DataLoader를 사용하여 Minist dataset를 이용하는 부분만 차이가 나고, 데이터량이 많아서 시간이 좀 많이 걸리는 부분입니다. 
입력 DataLoader를 이용하는 것은 4장에서 잠시 다루었기 때문에,  시간을 줄이기 위해서 cuda gpu를 사용하는 부분을 추가했습니다.
입력변수와 network상의 변수의 torch.Tensor를 cuda() 함수를 통해서 선언하면 됩니다.
python
is_cuda =  torch.cuda.is_available()
if is_cuda 
Step1:  1. 입력DataLoader 설정
train 데이터로 loader를 지정 (dataset은 Minist, batch 사이즈 50, shuffle를 실행)
test 데이터로 loader를 지정 (dataset은 Minist, batch 사이즈 1000)
Step2:  2. 사전 설정
* model
* loss
* opimizer
Step3:  3. Trainning loop
* (입력 생성)
* model 생성
* loss 생성
* zeroGrad
* backpropagation
* optimizer step (update model parameter)
Summary 추가 및 출력하기
간단하게 loss와 accuracy를 list에 추가하도록 나중에 matplotlib를 이용하여 출력하겠습니다.
이 부분은 train_loss, train_accu라는 list에 loss와 accuracy를 append하면 됩니다.
물론 Tensorboard같은 별도의 전용 tool이 있으면 편리하겠지만, 간단히 확인할 경우 큰 불편사항은 없습니다.
일단 빈 list를 선언한 다음,
python
train_loss = []
train_accu = []
train과정이나 test과정에 loss와 accuracy를 추가하면 됩니다.
```python
pred = output.data.max(1)[1]
accuracy = pred.eq(target.data).sum()/batch_size
train_loss.append(loss.data[0])
train_accu.append(accuracy)
```
Step4:  4. Predict & Evaluate
Step5:  5. save model parameter
훈련시킨 model의 parameter를 파일에 저장한다. 다음장에서 저장한 parameter를 restore할 것입니다.
Step6:  6. plot images which failed to predict
여러장을 표시할 경우 별로 함수를 이용하여도 되나, pytorch에서 제공하는 함수를 이용하여 출력하여 보았습니다.
python
torchvision.utils.make_grid(tensor, nrow=8, padding=2)
plt.imshow할때도 약간 주의해야 하는데, array는 colordepth x Height x Width 되어 있지만, Height x Width x colordepth 형태로 바꾸어야 해서 transpose(1, 2, 0)를 수행하였습니다.
<ASSISTANT_TASK:>
Python Code:
%matplotlib inline
Explanation: Minist 예제
Minist 예제를 살펴봅시다. 사실 minist 예제는 3장 다룬 기초적인 Neural Networw와 거의 동일 합니다.   
단지, 입력 DataLoader를 사용하여 Minist dataset를 이용하는 부분만 차이가 나고, 데이터량이 많아서 시간이 좀 많이 걸리는 부분입니다. 
입력 DataLoader를 이용하는 것은 4장에서 잠시 다루었기 때문에,  시간을 줄이기 위해서 cuda gpu를 사용하는 부분을 추가했습니다.
입력변수와 network상의 변수의 torch.Tensor를 cuda() 함수를 통해서 선언하면 됩니다.
python
is_cuda =  torch.cuda.is_available()
if is_cuda :  model.cuda()
if is_cuda :  data, target = data.cuda(), target.cuda()
End of explanation
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)
Explanation: 1. 입력DataLoader 설정
train 데이터로 loader를 지정 (dataset은 Minist, batch 사이즈 50, shuffle를 실행)
test 데이터로 loader를 지정 (dataset은 Minist, batch 사이즈 1000)
End of explanation
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)
Explanation: 2. 사전 설정
* model
* loss
* opimizer
End of explanation
# 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])
plt.plot(train_accu)
plt.plot(train_loss)
Explanation: 3. Trainning loop
* (입력 생성)
* model 생성
* loss 생성
* zeroGrad
* backpropagation
* optimizer step (update model parameter)
Summary 추가 및 출력하기
간단하게 loss와 accuracy를 list에 추가하도록 나중에 matplotlib를 이용하여 출력하겠습니다.
이 부분은 train_loss, train_accu라는 list에 loss와 accuracy를 append하면 됩니다.
물론 Tensorboard같은 별도의 전용 tool이 있으면 편리하겠지만, 간단히 확인할 경우 큰 불편사항은 없습니다.
일단 빈 list를 선언한 다음,
python
train_loss = []
train_accu = []
train과정이나 test과정에 loss와 accuracy를 추가하면 됩니다.
```python
pred = output.data.max(1)[1]
accuracy = pred.eq(target.data).sum()/batch_size
train_loss.append(loss.data[0])
train_accu.append(accuracy)
```
End of explanation
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)))
Explanation: 4. Predict & Evaluate
End of explanation
checkpoint_filename = 'minist.ckpt'
torch.save(model.state_dict(), checkpoint_filename)
Explanation: 5. save model parameter
훈련시킨 model의 parameter를 파일에 저장한다. 다음장에서 저장한 parameter를 restore할 것입니다.
End of explanation
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))
Explanation: 6. plot images which failed to predict
여러장을 표시할 경우 별로 함수를 이용하여도 되나, pytorch에서 제공하는 함수를 이용하여 출력하여 보았습니다.
python
torchvision.utils.make_grid(tensor, nrow=8, padding=2)
plt.imshow할때도 약간 주의해야 하는데, array는 colordepth x Height x Width 되어 있지만, Height x Width x colordepth 형태로 바꾸어야 해서 transpose(1, 2, 0)를 수행하였습니다.
End of explanation
<END_TASK>