해당 게시글은 개인적인 복습을 위해 PyTorch tutorial을 기반으로 설명을 덧붙이고 코드를 수정하며 정리한 글입니다.
Training a classifier
about data
데이터를 다룰 때 유용한 packages
Image data : Pillow, OpenCV
Audio data : scipy, librosa
Text data : NLTK, SpaCy
사용한 데이터 : CIFAR-10은
10개의 classes
('airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck')로 이루어진
3 x 32 x 32 size의 image data이다.
(3-channel color images of 32x32 pixels in size)
Training an image classifier
1. Load and normalize CIFAR10
2. Define a Convolutional Neural Network
3. Define a loss function
4. Train the network on the training data
5. Test the network on the test data
Load and normalize CIFAR10
import torch
import torchvision
import torchvision.transforms as transforms
torchvision dataset은 기본적으로 [0,1]의 range를 갖는 이미지이다.
따라서 이를 활용하기 용이하도록 [-1, 1]의 range를 갖는 tensor로 정규화하는데,
이 때, 평균 0.5를 빼고 표준편자 0.5로 나누는 형태를 취한다.
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
batch_size = 4
trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,
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=batch_size,
shuffle=False, num_workers=2)
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)))
plt.show()
# get some random training images
dataiter = iter(trainloader)
images, labels = next(dataiter)
# show images
imshow(torchvision.utils.make_grid(images))
# print labels
print(' '.join(f'{classes[labels[j]]:5s}' for j in range(batch_size)))
Define a Convolutional Neural Network
import torch.nn as nn
import torch.nn.functional as F
class Net(nn.Module):
def __init__(self):
super().__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 = torch.flatten(x, 1) # flatten all dimensions except batch
x = F.relu(self.fc1(x))
x = F.relu(self.fc2(x))
x = self.fc3(x)
return x
net = Net()
Define a Loss function and optimizer
regression 문제에서는 주로 MSE를 사용했지만 classifier 문제의 경우에는 Cross-Entropy와 momentum을 활용한 SGD가 많이 사용된다.
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
Train the network
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; data is a list of [inputs, labels]
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(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')
running_loss = 0.0
print('Finished Training')
생성된 model을 python의 pickle 형태로 저장할 수 있다.
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
Test the network on the test data
dataiter = iter(testloader)
images, labels = next(dataiter)
# print images
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join(f'{classes[labels[j]]:5s}' for j in range(4)))
아래의 과정을 통해 기존에 학습된 model을 불러올 수 있다.
net = Net()
net.load_state_dict(torch.load(PATH))
outputs = net(images)
결과값은 10개 class들에 대한 값들로 나오며 해당 값들 중 가장 큰 값의 class를 output으로 선정한다.
_, predicted = torch.max(outputs, 1)
print('Predicted: ', ' '.join(f'{classes[predicted[j]]:5s}'
for j in range(4)))
correct = 0
total = 0
# since we're not training, we don't need to calculate the gradients for our outputs
with torch.no_grad():
for data in testloader:
images, labels = data
# calculate outputs by running images through the network
outputs = net(images)
# the class with the highest energy is what we choose as prediction
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print(f'Accuracy of the network on the 10000 test images: {100 * correct // total} %')
10개의 label 중 하나를 고르는 분류 문제에서 정답률이 56%라는 뜻은 모델이 무언가를 학습했다는 의미이다.
특정 label에 대한 정확도는 아래와 같다.
# prepare to count predictions for each class
correct_pred = {classname: 0 for classname in classes}
total_pred = {classname: 0 for classname in classes}
# again no gradients needed
with torch.no_grad():
for data in testloader:
images, labels = data
outputs = net(images)
_, predictions = torch.max(outputs, 1)
# collect the correct predictions for each class
for label, prediction in zip(labels, predictions):
if label == prediction:
correct_pred[classes[label]] += 1
total_pred[classes[label]] += 1
# print accuracy for each class
for classname, correct_count in correct_pred.items():
accuracy = 100 * float(correct_count) / total_pred[classname]
print(f'Accuracy for class: {classname:5s} is {accuracy:.1f} %')
Training on GPU
CUDA 사용 여부 확인 코드
device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')
# Assuming that we are on a CUDA machine, this should print a CUDA device:
print(device)
net.to(device)
inputs, labels = data[0].to(device), data[1].to(device)
del dataiter
'정리 > Pytorch' 카테고리의 다른 글
[Pytorch 꿀팁] Cuda:out of memory (0) | 2023.03.24 |
---|---|
[Pytorch 기본] Neural Network (0) | 2023.01.21 |
[Pytorch 기본] Autograd (0) | 2023.01.17 |
[Pytorch 기본] Tensor (2) | 2023.01.17 |