VGG
참고
VGG
ICLR 2015
Abstract
convolutional network의 깊이에 따른 성능을 확인하는 것이 목적
주요한 contribution은 $3 \times 3$ 크기를 가지는 작은 convoliution 필터들을 사용하여 네트워크의 깊이를 깊게 만들어 평가
이를 통하여 16-19 개의 가중치 레이어로 확장하여 이전의 연구들 보다 좋은 성능을 가지는 것을 보임
이 모델을 사용하여 ILSVRC-2014 대회에서 localization 분야와 classification 분야에서 각각 1등과 2등을 하는 좋은 성능을 보임
ConvNet Configurations
Architecture
네트워크 깊이가 어떤 영향을 주는 지 연구 하기 위해 설계된 네트워크로 동일한 kernel size에 convolution의 개수를 늘리는 방식으로 구성됨
위의 Table에서 처럼 11 layer, 13 layer, 16 layer, 19 layer 의 네트워크를 테스트함
위의 표에서 D는 VGG-16, E는 VGG-19를 의미
Convolution layer의 stride는 1, $3 \times 3$ filter의 경우 spatial resolution을 유지하기 위해 padding은 1로 고정
Resolution의 경우 max pooling으로 줄이는데 window의 경우 $2 \times 2$ 그리고 stride는 2로 고정하여 적용
모든 hidden layer에는 ReLU 적용
VGG 이전에는 비교적 큰 Receptive Field를 가지는 $11 \times 11$, $7 \times 7$ 사용
$7 \times 7$ 한 번 사용하는 것보다 $3 \times 3$ 크기를 가지는 filter를 3번 쌓아 구현하면 ReLU 함수의 중복 사용으로 인해 비선형성이 증가하게 되어 모델의 성능이 증가함
또한, $7 \times 7$ 크기의 필터의 학습 파라미터의 수는 49 개이고 $3 \times 3$ 크기의 학습 파라미터의 수는 27개로, 학습할 파라미터의 수가 줄어듬을 확인
구현
Torchvision에 구현되어 있는 VGG 참고
VGG16, 19만 적용
Normalization 포함한 구현
cfg = {
'vgg16': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'],
'vgg19': [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M']
}
class VGG(nn.Module):
def __init__(self, features, num_classes=1000):
super().__init__()
self.features = features
self.classifier = nn.Sequential(
nn.Linear(512*7*7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.features(x)
x = x.view(x.size(0), -1)
out = self.classifier(x)
return out
def make_layers(cfg):
layers = []
input_channel = 3
for l in cfg:
if l == "M":
layers += [nn.MaxPool2d(kernel_size=2, stride=2)]
continue
layers += [nn.Conv2d(input_channel, l, kernel_size=3, stride=1, padding=1)]
layers += [nn.BatchNorm2d(l)]
layers += [nn.ReLU(inplace=True)]
input_channel = l
return nn.Sequential(*layers)
def vgg16(num_classes=1000):
return VGG(make_layers(cfg['vgg16']), num_classes=num_classes)
def vgg19(num_classes=1000):
return VGG(make_layers(cfg['vgg19']), num_classes=num_classes)