VGG CIFAR-10에 적용 및 정리
모두의 딥러닝 시즌2 - Pytorch를 참고 했습니다.
모두의 딥러닝 시즌2 깃헙
import torch
import torch.nn as nn
import torch.optim as optim
import torchvision
import torchvision.transforms as transforms
device = 'cuda' if torch.cuda.is_available() else 'cpu'
torch.manual_seed(123)
if device =='cuda':
torch.cuda.manual_seed_all(123)
transform = transforms.Compose(
[transforms.ToTensor(),
transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])
trainset = torchvision.datasets.CIFAR10(root='./cifar10', train=True,
download=True, transform=transform)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=512,
shuffle=True, num_workers=0)
testset = torchvision.datasets.CIFAR10(root='./cifar10', 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')
- torchvision.transforms.Compose(transforms) -> 여러개의 데이터 transformer을 묶어놓을 수 있다.
- torchvision.transforms.functional.normalize(tensor, mean, std, inplace=False) -> data를 normalize한다. 현재는 적당한 값으로 집어 넣었지만, 더 좋은 성능을 내기 위해서는 trainset에 대해서 mean과 std를 알아낼 필요가 있다.
- CIFAR-10에는 10개의 class가 있다.
import matplotlib.pyplot as plt
import numpy as np
%matplotlib inline
def imshow(img):
img = img/2 + 0.5
npimg = img.numpy()
plt.imshow(np.transpose(npimg, (1,2,0)))
plt.show()
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print(' '.join('%5s' % classes[labels[j]] for j in range(4)))
testset 중 4개를 표시해본다.
import vgg_01
- 이전에 저장해둔 코드가 있으면 불러온다.
- 같은 디렉토리(폴더) 내의 vgg_01.py 이름을 가진 파일을 불러온다.
- ipynb 파일은 불러올 수 없으므로, jupyer notebook을 이용해 코드를 짯다면, ipython nbconvert --to script vgg_01.ipynb를 이용해 .py로 변환한다.
cfg = [32,32,'M', 64,64,128,128,128,'M',256,256,256,512,512,512,'M'] #13 + 3 =vgg16
class VGG(nn.Module):
def __init__(self, features, num_classes=1000, init_weights=True):
super(VGG, self).__init__()
self.features = features
#self.avgpool = nn.AdaptiveAvgPool2d((7, 7))
self.classifier = nn.Sequential(
nn.Linear(512 * 4 * 4, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, num_classes),
)
if init_weights:
self._initialize_weights()
def forward(self, x):
x = self.features(x)
#x = self.avgpool(x)
x = x.view(x.size(0), -1)
x = self.classifier(x)
return x
def _initialize_weights(self):
for m in self.modules():
if isinstance(m, nn.Conv2d):
nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu')
if m.bias is not None:
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.BatchNorm2d):
nn.init.constant_(m.weight, 1)
nn.init.constant_(m.bias, 0)
elif isinstance(m, nn.Linear):
nn.init.normal_(m.weight, 0, 0.01)
nn.init.constant_(m.bias, 0)
- CIFAR-10은 image size가 32323으로, 작은 편이다.
- 기존 VGG의 형태를 변경한다.
- avgpool 제거, feature을 거친 후 최종단 output (512, 4, 4)로 줄어듬
- num_class = 10
vgg16= VGG(vgg_01.make_layers(cfg),10,True).to(device)
a = torch.Tensor(1,3,32,32).to(device)
out = vgg16(a)
print(out)
tensor([[-5.5271e+30, 2.0224e+30, -1.0700e+30, 2.5091e+30, 1.5906e+30,
-5.5477e+29, -2.7936e+30, 1.4075e+29, -5.7797e+29, 1.5343e+30]],
device='cuda:0', grad_fn=)
dataset을 다운 받지 못했다면, 이렇게 랜덤 input을 만들어 테스트 해 볼 수도 있다.
criterion = nn.CrossEntropyLoss().to(device)
optimizer = torch.optim.SGD(vgg16.parameters(), lr=0.005, momentum=0.9)
lr_sche = optim.lr_scheduler.StepLR(optimizer, step_size=5, gamma=0.9)
torch.optim.lr_scheduler.StepLR(optimizer, step_size, gamma=0.1, last_epoch=-1) -> 5 step을 거칠 때마다, lr을 x0.9만큼 줄여주면서 학습시킨다.
print(len(trainloader))
epochs = 30
for epoch in range(epochs):
running_loss = 0.0
lr_sche.step()
for i, data in enumerate(trainloader, 0): # 0부터 시작
inputs, labels = data
inputs = inputs.to(device)
labels = labels.to(device)
optimizer.zero_grad()
outputs = vgg16(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
if i % 30 == 29:
print('[%d, %5d] loss: %.3f' %
(epoch+1, i+1, running_loss/30))
running_loss = 0.0
print('finished')
98
[1, 30] loss: 2.298
[1, 60] loss: 2.288
[1, 90] loss: 2.227
[2, 30] loss: 2.083
...
dataiter = iter(testloader)
images, labels = dataiter.next()
imshow(torchvision.utils.make_grid(images))
print('GT: ', ' '.join('%5s' % classes[labels[j]] for j in range(4)))
outputs = vgg16(images.to(device))
_, 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
images = images.to(device)
labels = labesl.to(device)
outputs = vgg16(images)
_, predicted = torch.max(outputs.data, 1)
total += labels.size(0)
correct += (predicted == labels).sum().item()
print('Acc : %d %%' % (
100*correct / total))
'프로그래머 > Pytorch' 카테고리의 다른 글
[pytorch] linear regression class를 nn.Sequential로 간단하게 표현 (0) | 2020.06.16 |
---|---|
[Pytorch] 기초 강의 day1 (0) | 2020.06.15 |
[Pytorch] VGG 구현 및 정리 (2) | 2020.06.07 |
[Pytorch] MNIST 간단한 CNN 구현 및 정리 (0) | 2020.06.07 |
[Pytorch tutorial] Autograd: 자동미분 (0) | 2020.06.04 |