VGG-Net은 2014년에 ILSVRC에서 GoogleNet 다음으로 우수한 성능을 보인 CNN 아키텍쳐이다. 이전에 Convolution에서 사용된 필터들보다 작은 3x3 필터를 여러번 사용하는 방식을 채택했고, 레이어를 여러개 쌓아 분류 성능을 높였다. 논문의 내용을 토대로 VGG-Net 의 구조를 더 자세하게 살펴보도록 하겠다.
논문 링크 https://arxiv.org/abs/1409.1556
Very Deep Convolutional Networks for Large-Scale Image Recognition
In this work we investigate the effect of the convolutional network depth on its accuracy in the large-scale image recognition setting. Our main contribution is a thorough evaluation of networks of increasing depth using an architecture with very small (3x
arxiv.org
VGG-Net 에서는 7x7, 5x5 처럼 크기가 큰 필터들을 사용하는 대신 모델 전반에 걸쳐 3x3 필터를 여러번 쌓 방식을 채택했다. 3x3 필터를 2번 쌓으면 5x5 필터를 사용했을 때와 같은 크기로 이미지가 축소되고, 3x3 필터를 3번 쌓으면 7x7 필터를 사용했을 때와 같은 크기로 이미지가 축소된다.

필터 적용 사이에 활성화함수를 통해 비선형성을 추가할 수 있어 더 많은 정보를 추출할 수 있고, 가중치의 갯수도 더 적기 때문에 (3x3x2 < 5x5) 학습시켜야 하는 가중치의 양이 줄어 연산의 양도 줄어든다는 장점이 있다. 1x1 Convolution Layer 역시 사용하는데, 이는 Feature Map 의 크기를 변화시키지 않으면서 비선형성을 추가하기 위함이다.

논문에서는 깊이와 구조를 조금씩 다르게 하면서 5가지 (A~E) 구조를 선보인다. 모델의 깊이가 깊어질수록 뛰어난 성능이 나왔다고 한다. 아래는 D의 구조이다.

- Input 단계
224x224x3 크기의 이미지를 입력으로 받는다. 여기서 주어진 이미지를고정된 크기로 줄이기 위해서 원본 이미지에 Random Crop 을 적용한다. 이후 데이터 증강을 위해 AlexNet과 마찬가지로 Horizontal Flipping, RGB colour shift 등을 진행한다.
- Convolution 단계
모든 필터의 크기는 3x3, stride=1, padding=1 을 적용해 Feature Map 의 크기를 유지한다. Downsampling은 Max Pooling을 통해서만 진행된다. (2x2 Max Pooling, stride=2) 채널의 숫자를 64, 128, 256, 512개로 깊어질수록 증가시킨다. 각 Convolution 뒤에는 ReLU 활성화 함수를 적용해 비선형성을 추가한다. 일반적으로 필터의 크기에 대해 설명할 때 "3x3, 채널 수 3개" 이런 식으로 이야기하지만 아래에서는 "3x3x3 필터" 이렇게 3차원으로 설명하겠다. (개인적으로 그렇게 하는게 파라미터 수가 몇개인지 더 와닿기 때문에)
첫번째 블록에서는 224x224x3 크기의 이미지를 입력으로 받은 뒤 3x3x3 필터 64개 convolution, 3x3x64 필터 64개 convolution을 적용한다. 여기에 2x2 Max Pooling을 통한 Downsampling 으로 Feature Map의 크기는 112x112x64 가 된다.
두번째 블록에서는 3x3x64 필터 128개 convolution, 3x3x128 필터 128개 convolution을 적용한다. 여기에 2x2 Max Pooling을 통한 Downsampling 으로 Feature Map의 크기는 56x56x128 이 된다.
세번째 블록에서는 순서대로 3x3x128 필터 256개 convolution, 3x3x256 필터 256개 convolution 두 번을 진핸한 후 2x2 Max Pooling으로 Downsampling 한다. Feature Map의 크기는 28x28x256 이 된다.
네번째 블록에서는 순서대로 3x3x256 필터 512개 convolution, 3x3x512 필터 512개 convolution 두 번을 진핸한 후 2x2 Max Pooling으로 Downsampling 한다. Feature Map의 크기는 14x14x512 가 된다.
다섯번째 블록에서는 3x3x512 필터 512개 convolution 세번을 진핸한 후 2x2 Max Pooling으로 Downsampling 한다. Feature Map의 크기는 7x7x512 가 된다. 이후에는 Fully-Connected Layer 들을 통과하고 최종적으로 Softmax 함수를 통해 이미지를 분류한다.
아래는 VGG-Net 13 구현 코드이다.
import torch
import torch.nn as nn
class VGGNet(nn.Module):
def __init__(self, num_classes=1000):
super().__init__()
self.features = nn.Sequential(
# Block 1
nn.Conv2d(3, 64, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(64, 64, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Block 2
nn.Conv2d(64, 128, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Block 3
nn.Conv2d(128, 256, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(256, 256, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Block 4
nn.Conv2d(256, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
# Block 5
nn.Conv2d(512, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.Conv2d(512, 512, kernel_size=3, padding=1, stride=1),
nn.ReLU(inplace=True),
nn.MaxPool2d(kernel_size=2, stride=2),
)
self.classifier = nn.Sequential(
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, 4096),
nn.ReLU(inplace=True),
nn.Dropout(0.5),
nn.Linear(4096, num_classes)
)
def forward(self, x):
x = self.features(x)
x = torch.flatten(x, start_dim=1)
x = self.classifier(x)
return x'컴퓨터 비전' 카테고리의 다른 글
| R-CNN (Regions with CNN features) (0) | 2026.02.10 |
|---|---|
| ResNet의 구조 (0) | 2026.01.30 |
| AlexNet 구현, CIFAR-10 이미지 분류하기 (0) | 2026.01.14 |
| AlexNet의 구조와 구현 (0) | 2026.01.10 |
| 이미지에서의 Edge Detection (First Derivative, Laplacian, Canny Edge Detection) (0) | 2026.01.04 |