이 페이지는 Deep Learning의 대표 논문 VggNet(2014)에 대한 내용입니다.
VGGNet은 19 layer를 지닌 깊은 network로 ILSVRC 2014 대회에서 2등을 차지했습니다.
역대 ILSVRC 우승작 network의 깊이는 8 layer에 불가했습니다.
깊이가 깊어짐에 따라 overfitting, gradient vanishing, 연산량 문제가 생기기 때문에 이러한 문제를 해결하기 위해 VGGNet은 다음과 같은 특징을 갖습니다.
모델의 Kernel size를 3x3 사이즈로 하여 파라미터 줄임.
파라미터가 줄었기 때문에 더 deep한 network 구현 가능.
다음과 같은 특징들은 VGGNet이 deep함과 동시에 간단한 구현이 가능해 졌습니다.
VGG 모델은 딥러닝 기반 컴퓨터 비전 모델의 시대를 열었던 AlexNet(2012)의 모델보다 깊이가 2배 이상 깊은 네트워크의 학습에 성공하였고, ImageNet Challenge에서 AlexNet의 오차율을 절반(16.4 > 7.3)으로 줄였습니다.
본 논문의 핵심 아이디어인 3x3 kernel만 사용합니다(C 제외).
그 이유는 기존의 7x7 conv layer를 한번 사용하면 비선형 변환을 한번 하게 되지만 3번의 3x3 conv layer를 사용하게 되면 세번의 비선형 변환이 가능하기때문입니다.
CNN Layer를 지난 후의 채널의 수가 C라고 할때
3개의 3x3 conv layer의 파라미터 수
7x7 conv layer의 파라미터 수
따라서 파라미터 수도 적고 비선형 변환을 많이 할 수 있습니다.
이때 활성함수는 ReLU을 사용하였고, stride와 padding은 1입니다.
5개의 MaxPooling 연산이 있습니다.
kernel size는 2x2 이고 stride는 2입니다.
세개의 Fully Connected Layer를 적용합니다.
세번째는 1000개의 클래스에 대해서 1000개의 채널을 가지고 softmax를 적용합니다.
아래 표는 그들이 실험에 사용한 6개의 구조를 보여줍니다.
열마다 다른 깊이의 모델을 보여주며 ABCDE로 나누고 각각의 다른 점은 깊이만 다릅니다.
import torch.nn as nn
from torchsummary import summary
Vgg_types = {'VGG16':[64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M']}
class VggNet16(nn.Module):
def __init__(self, model, in_channel=3, num_classes=10):
super(VggNet16, self).__init__()
self.in_channel = in_channel
self.conv = self.make_layers(Vgg_types[model])
self.fc1 = nn.Sequential(
nn.Linear(512*7*7, 4096)
)
self.fc2 = nn.Sequential(
nn.Linear(4096, 4096)
)
self.output = nn.Sequential(
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.conv(x)
x = x.view(x.size(0), -1)
fc1 = self.fc1(x)
fc2 = self.fc2(fc1)
output = self.output(fc2)
return output
def make_layers(self, arcitecture):
layers = []
in_channel = self.in_channel
for x in arcitecture:
if type(x) == int:
out_channel = x
layers += [nn.Conv2d(in_channel, out_channel, kernel_size=3, stride=1, padding='same'),
nn.ReLU()]
in_channel = x
elif x == 'M':
layers += [nn.MaxPool2d(2,2)]
return nn.Sequential(*layers)
summary(VggNet16('VGG16', in_channel=3, num_classes=10).cuda(), (3,224,224))