What aoubt data?
일반적으로 이미지, 텍스트, 비디오, 오디오 데이터를 다룰 때 numpy array로 데이터를 읽고 torch의 tensor로 변환한다. 각 데이터마다 유용하게 사용하는 라이브러리가 존재한다.
- Images : Pillow, OpenCV
- Audio : scipy, librosa
- Text : NLTK, SpaCy
특히 vision 분야에서는 torchvision
을 사용해서 유명한 데이터셋을 불러서 사용할 수 있다.
torchvision.datasets
, torch.utils.data.DataLoader
유명 이미지 데이터셋 중 하나인 CIFAR10을 사용해보자.
CIFAR10은 RGB 컬러 32*32 사이즈 이미지의 총 10개의 카테고리로 이루어져있는 이미지 데이터셋이다.
Training an image classifier
데이터셋을 읽고 학습 및 테스트 하는 과정은 다음과 같다.
torchvision
을 사용해서 CIFAR10 데이터셋의 train/test dataset을 만든다.
- CNN 모델을 만든다.
- loss function을 정의한다.
- training dataset을 사용해서 CNN을 학습시킨다.
- test dataset을 사용해서 학습된 CNN을 테스트한다.
1. CIFAR10 dataset 읽고 정규화하기
import torch
import torchvision
import torchvision.transforms as transforms
torchvision에서 제공하는 데이터셋들은 PILImage 형태로 [0,1] 범위의 값으로 표현된다. 이것을 [-1, 1] 범위로 normalization 해준다.
transform = transforms.Compose(
[transforms.ToTensor(), # Tensor화
transforms.Normalize((0.5,0.5,0.5), (0.5,0.5,0.5))]) # Normalization
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')
Downloading https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz to ./data/cifar-10-python.tar.gz
Extracting ./data/cifar-10-python.tar.gz to ./data
Files already downloaded and verified
학습 이미지가 어떻게 생겼는지 matplotlib
을 사용해서 확인해보자.
import matplotlib.pyplot as plt
import numpy as np
def imshow(img):
img = img / 2 + 0.5
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1, 2, 0)))
plt.show()
dataiter = iter(trainloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
2. CNN 만들기
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. Loss function과 optimizer 생성
classification 문제에서 loss function은 cross-entropy loss가 많이 사용된다.
optimizer는 SGD를 사용한다.
import torch.optim as optim
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
4. 네트워크 학습 시작
데이터셋을 몇 번 반복할 것인지 횟수를 뜻하는 epoch만큼 트레이닝을 한다.
for epoch in range(2):
running_loss = 0.0 # epoch마다 loss 저장
for i, data in enumerate(trainloader, 0):
inputs, labels = data
optimizer.zero_grad() # optimizer 초기화
outputs = net(inputs)
loss = criterion(outputs, labels)
loss.backward() # backprop part
optimizer.step() # backprop part
running_loss += loss.item()
if i % 2000 == 1999:
print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 2000))
running_loss = 0.0
print('Finished Training')
[1, 2000] loss: 2.198
[1, 4000] loss: 1.829
[1, 6000] loss: 1.644
[1, 8000] loss: 1.564
[1, 10000] loss: 1.489
[1, 12000] loss: 1.474
[2, 2000] loss: 1.379
[2, 4000] loss: 1.347
[2, 6000] loss: 1.340
[2, 8000] loss: 1.338
[2, 10000] loss: 1.313
[2, 12000] loss: 1.285
Finished Training
학습한 모델을 저장하면 나중에 저장한 파일을 불러서 사용할 수 있다.
PATH = './cifar_net.pth'
torch.save(net.state_dict(), PATH)
Test data 적용해보기
학습시킨 CNN 모델이 처음 보는 데이터에도 좋은 성능을 보이는지 test data로 확인한다.
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print('GroundTruth: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
먼저 테스트 데이터셋 몇 개를 확인해본다.
net = Net()
net.load_state_dict(torch.load(PATH)) # 저장한 모델 불러오기
outputs = net(images)
_, predicted = torch.max(outputs, 1) # 제일 높은 값의 인덱스를 반환함
print('Predicted: ', ' '.join('%5s' % classes[predicted[j]]
for j in range(4)))
예측한 값 중 가장 높은 값의 인덱스를 반환해서 어떤 카테고리에 해당하는지 출력해본다.
Predicted: cat ship ship plane
꽤 좋은 결과가 나오는 것을 확인할 수 있다.
이것을 test dataset 전체에 대해 적용해보자.
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))
Accuracy of the network on the 10000 test images: 56 %
결과적으로 10000개 테스트 이미지에 대한 정확도는 56%였다.
이번에는 카테고리 별 정확도를 확인한다.
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]))
Accuracy of plane : 69 %
Accuracy of car : 78 %
Accuracy of bird : 38 %
Accuracy of cat : 37 %
Accuracy of deer : 43 %
Accuracy of dog : 44 %
Accuracy of frog : 59 %
Accuracy of horse : 67 %
Accuracy of ship : 61 %
Accuracy of truck : 61 %
카테고리 별 정확도를 분석해서 네트워크가 어떤 카테고리에 대해 정확도가 낮은지 알 수 있기 때문에 이러한 분석은 모델의 성능을 개선하는데 도움이 되는 정보가 된다.
Training on GPU
PyTorch가 좋은 이유는 CPU보다 빠른 연산 수행이 가능한 GPU를 활용하여 네트워크 학습이 가능하다는 것이었다. GPU를 사용해서 트레이닝하려면 먼저 CUDA가 설치되어 있어야 한다.
CUDA가 설치되어 사용 가능한 GPU가 있으면 cuda:0
를 출력한다.
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
print(device)
cuda:0
이제 GPU에서 연산 가능한 변수들을 모두 GPU로 옮긴다.
net.to(device)
inputs, labels = data[0].to(device), data[1].to(device)
GPU 활용의 효과는 네트워크가 클수록 더 잘 나타난다.
CPU보다 더, single GPU보다 더 가속 효과를 내려면 Multi-GPU를 사용하면 된다.
PyTorch에서는 Data Parallelism
에 대해서도 지원한다.
Uploaded by Notion2Tistory v1.1.0