https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html
Training a classifier (분류기 훈련)
신경망을 어떻게 정의하고, 손실 계산과, 네트워크의 가중치값들을 업데이트하는 방법에 대해 보아왔습니다.What about data?
이미지, 오디오, 텍스트, 비디오 데이터를 다루어야 할때, 당신은 numpy 배열로 데이터를 로드하는 표준 파이썬 패키지를 사용 할 수 있습니다. 그리고 당신은 이 배열을 torch.*Tensor로 변경할 수 있습니다.- 이미지는 Pillow, OpenCV 패키지가 유용합니다.
- 오디오는 scipy 와 librosa
- 텍스트의 경우 Python 또는 Cython 기반 로딩, 또는 NLTK 및 SpaCy가 유용합니다.
비전의 경우 특별히, torchvision이라고 불리는 패키지가 만들어 졌습니다. 이것은 Imagenet, CIFAR10, MNIST 들과 같은 공통 데이터 셋과 로더들을 가지고 있습니다.
이것은 편리함을 제공해주고 중복 코드를 피하게 해줍니다.
이 예제에서는 CIFAR10 데이터셋을 사용할것 입니다. ‘airplane’, ‘automobile’, ‘bird’, ‘cat’, ‘deer’, ‘dog’, ‘frog’, ‘horse’, ‘ship’, ‘truck’ 데이터 셋을 가지고 있고, CIFAR10 이미지들의 크기는 32*32*3인데 3은 3채널로 이미지의 색을 의미합니다. 아마도 공부전이긴 하지만 RGB각각 8bit씩이지 않을까요?
Training an image classifier (이미지 분류기의 훈련)
아래 순서로 할것입니다.
1. torchvision을 사용하여 CIFAR10 훈련 및 테스트 데이터 세트 로드 및 정규화
CIFAR10 훈련 로드하고 정규화 합니다.
2. 컨볼루션 NN 을 정의합니다.
3. 손실 함수를 정의합니다
4. 훈련 데이터로 네트워크를 훈련합니다.
5. 테스트 데이터로 네트워크를 테스트합니다.
1. CIFAR10 정규화 및 로딩
torchvision을 사용하면, CIFAR10을 로드하는 것이 매우 쉽습니다.import torch import torchvision import torchvision.transforms as transforms
torchvision 데이터셋의 출력은 [0, 1] 범위의 PILImage 이미지입니다. 정규화 된 범위의 [-1, 1]의 텐서로 변환합니다.
import시 transforms를 합니다. 위 설명처럼 tensor로 변경할때 사용할 예정입니다.
transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=2) classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
Out:
Files already downloaded and verified
Files already downloaded and verified
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data\cifar-10-python.tar.gz Files already downloaded and verified
import matplotlib.pyplot as plt import numpy as np # functions to show an image def imshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) # get some random training images dataiter = iter(trainloader) images, labels = dataiter.next() # show images imshow(torchvision.utils.make_grid(images)) # print labels print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
위와 같은 코드를 실행해서 에러가 발생한다면 아래 링크를 참조하여 수정하면됩니다.
https://discuss.pytorch.org/t/brokenpipeerror-errno-32-broken-pipe-when-i-run-cifar10-tutorial-py/6224/3
Original (not working):
# ... code ...
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=2)
# ... code ...
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=2)
# ... code ...
Modified (working):
# ... code ...
trainloader = torch.utils.data.DataLoader(trainset, batch_size=4,
shuffle=True, num_workers=0)
# ... code ...
testloader = torch.utils.data.DataLoader(testset, batch_size=4,
shuffle=False, num_workers=0)
# ... code ...
Out:
ship truck horse horse
frog ship frog cat
실제 이미지도 볼 수 있는데 해당 시점에 출력하려면, plt.show()코드를 추가해야합니다.
마지막에 plt.show() # add code 코드를 추가하면 아래와 같은 이미지를 볼 수 있습니다.
2. Define a Convolution Neural Network
Neural Networks (신경 네트워크) 섹션 http://swlock.blogspot.com/2018/07/pytorch-tutorial-neuralnetworks.html 에서 class Net(nn.Module) 복사 한 다음 3 채널 이미지 (정의 된대로 1 채널 이미지 대신)를 사용하도록 수정합니다. nn.Conv2d(1, 6, 5) -> nn.Conv2d(3, 6, 5)
import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16 * 5 * 5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net()
3. Define a Loss function and optimizer
Classification Cross-Entropy 손실과 momentum을 가진 SGD를 사용합니다.
import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
4. Train the network
데이터 반복자를 이용하여 루프를 돌고 네트워크에 입력을 feed하고 최적화해야합니다.range(2)에 의해서 epoch 은 0, 1 루프를 돕니다.
for epoch in range(2): # loop over the dataset multiple times running_loss = 0.0 for i, data in enumerate(trainloader, 0): # get the inputs inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 2000 == 1999: # print every 2000 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training')
Out:
[1, 2000] loss: 2.199
[1, 4000] loss: 1.856
[1, 6000] loss: 1.688
[1, 8000] loss: 1.606
[1, 10000] loss: 1.534
[1, 12000] loss: 1.488
[2, 2000] loss: 1.420
[2, 4000] loss: 1.384
[2, 6000] loss: 1.336
[2, 8000] loss: 1.351
[2, 10000] loss: 1.309
[2, 12000] loss: 1.277
Finished Training
5. Test the network on the test data
훈련 데이터 세트에 대해 2회 네트워크를 훈련 시켰습니다.(epoch) 네트워크가 전혀 배운 게 없는지 확인해야합니다.
신경망이 출력하는 class label(여기에서는 이미지의 이름을 의미합니다.)을 예측하고 이를 정답과 비교하여 검사함으로써 이를 점검 할 것입니다. 예측이 정확하다면 샘플을 올바른 예측 목록에 추가합니다.
첫번째 스텝으로, 테스트 세트의 이미지를 표시 해봅니다. (큰 의미는 없는것 같습니다.)
dataiter = iter(testloader) images, labels = dataiter.next() # print images imshow(torchvision.utils.make_grid(images)) print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
Out:
GroundTruth: cat ship ship plane
outputs = net(images)
출력은 10 개의 클래스에 대한 에너지입니다. 클래스에 대한 에너지가 높을수록 네트워크는 이미지가 특정 클래스에 속한다고 생각합니다. 그래서 가장 높은 에너지 지수를 얻기위해서 max를 호출합니다.
_, predicted = torch.max(outputs, 1) print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4)))
Out:
Predicted: cat car car plane
전체 데이터셋에 대해서 어떻게 네트워크를 수행하는지 살펴봅니다.
correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 10000 test images: %d %%' % ( 100 * correct / total))
Out:
Accuracy of the network on the 10000 test images: 53 %
잘 수행한 것과 잘 못 학습한 것은 무엇일까요? 전체 클래스를 대상으로 정확도를 계산 해보았습니다.
class_correct = list(0. for i in range(10)) class_total = list(0. for i in range(10)) with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs, 1) c = (predicted == labels).squeeze() for i in range(4): label = labels[i] class_correct[label] += c[i].item() class_total[label] += 1 for i in range(10): print('Accuracy of %5s : %2d %%' % ( classes[i], 100 * class_correct[i] / class_total[i]))
Out:
Accuracy of plane : 60 %
Accuracy of car : 75 %
Accuracy of bird : 33 %
Accuracy of cat : 50 %
Accuracy of deer : 26 %
Accuracy of dog : 47 %
Accuracy of frog : 54 %
Accuracy of horse : 66 %
Accuracy of ship : 48 %
Accuracy of truck : 70 %
Training on GPU
GPU가 있는 상황은 아니라서 여기에서는 skip합니다.전체 소스 실행 화면 입니다.
전체소스
# -*- coding: utf-8 -*- import torch import torchvision import torchvision.transforms as transforms transform = transforms.Compose( [transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))]) trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform) trainloader = torch.utils.data.DataLoader(trainset, batch_size=4, shuffle=True, num_workers=0) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform) testloader = torch.utils.data.DataLoader(testset, batch_size=4, shuffle=False, num_workers=0) classes = ('plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck') import matplotlib.pyplot as plt import numpy as np # functions to show an image def imshow(img): img = img / 2 + 0.5 # unnormalize npimg = img.numpy() plt.imshow(np.transpose(npimg, (1, 2, 0))) # get some random training images dataiter = iter(trainloader) images, labels = dataiter.next() # show images imshow(torchvision.utils.make_grid(images)) # print labels print(' '.join('%5s' % classes[labels[j]] for j in range(4))) import torch.nn as nn import torch.nn.functional as F class Net(nn.Module): def __init__(self): super(Net, self).__init__() self.conv1 = nn.Conv2d(3, 6, 5) self.pool = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(6, 16, 5) self.fc1 = nn.Linear(16 * 5 * 5, 120) self.fc2 = nn.Linear(120, 84) self.fc3 = nn.Linear(84, 10) def forward(self, x): x = self.pool(F.relu(self.conv1(x))) x = self.pool(F.relu(self.conv2(x))) x = x.view(-1, 16 * 5 * 5) x = F.relu(self.fc1(x)) x = F.relu(self.fc2(x)) x = self.fc3(x) return x net = Net() import torch.optim as optim criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9) for epoch in range(2): # loop over the dataset multiple times running_loss = 0.0 for i, data in enumerate(trainloader, 0): # get the inputs inputs, labels = data # zero the parameter gradients optimizer.zero_grad() # forward + backward + optimize outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() # print statistics running_loss += loss.item() if i % 2000 == 1999: # print every 2000 mini-batches print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000)) running_loss = 0.0 print('Finished Training') dataiter = iter(testloader) images, labels = dataiter.next() # print images imshow(torchvision.utils.make_grid(images)) print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4))) outputs = net(images) _, predicted = torch.max(outputs, 1) print('Predicted: ', ' '.join('%5s' % classes[predicted[j]] for j in range(4))) correct = 0 total = 0 with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs.data, 1) total += labels.size(0) correct += (predicted == labels).sum().item() print('Accuracy of the network on the 10000 test images: %d %%' % ( 100 * correct / total)) class_correct = list(0. for i in range(10)) class_total = list(0. for i in range(10)) with torch.no_grad(): for data in testloader: images, labels = data outputs = net(images) _, predicted = torch.max(outputs, 1) c = (predicted == labels).squeeze() for i in range(4): label = labels[i] class_correct[label] += c[i].item() class_total[label] += 1 for i in range(10): print('Accuracy of %5s : %2d %%' % ( classes[i], 100 * class_correct[i] / class_total[i])) device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") # Assume that we are on a CUDA machine, then this should print a CUDA device: print(device)
실행 결과
Files already downloaded and verified Files already downloaded and verified deer truck ship ship [1, 2000] loss: 2.178 [1, 4000] loss: 1.845 [1, 6000] loss: 1.664 [1, 8000] loss: 1.567 [1, 10000] loss: 1.492 [1, 12000] loss: 1.459 [2, 2000] loss: 1.386 [2, 4000] loss: 1.342 [2, 6000] loss: 1.321 [2, 8000] loss: 1.321 [2, 10000] loss: 1.322 [2, 12000] loss: 1.254 Finished Training GroundTruth: cat ship ship plane Predicted: bird ship ship ship Accuracy of the network on the 10000 test images: 54 % Accuracy of plane : 64 % Accuracy of car : 79 % Accuracy of bird : 48 % Accuracy of cat : 27 % Accuracy of deer : 20 % Accuracy of dog : 61 % Accuracy of frog : 60 % Accuracy of horse : 67 % Accuracy of ship : 72 % Accuracy of truck : 41 % cpu
댓글 없음:
댓글 쓰기