딥러닝 연구에서 검증된 주요 신경망 아키텍처인 VGG, DenseNet, Inception, ResNet의 핵심 구조를 PyTorch로 구현하는 방법을 살펴봅니다.
1. VGG16 네트워크 구조
VGG는 3x3 커널을 가진 연속적인 컨벌루션 층과 풀링 층을 쌓아 깊은 특징 추출을 수행합니다. 매 풀링 단계마다 채널 수를 2배로 확장하는 특징이 있습니다.
import torch.nn as nn
class VGGNetwork(nn.Module):
def __init__(self, num_classes=1000):
super(VGGNetwork, self).__init__()
layers = []
in_c, out_c = 3, 64
for i in range(13):
layers.extend([nn.Conv2d(in_c, out_c, 3, padding=1), nn.ReLU(inplace=True)])
in_c = out_c
if i in [1, 3, 6, 9, 12]:
layers.append(nn.MaxPool2d(2, 2))
if i != 9: out_c *= 2
self.features = nn.Sequential(*layers)
self.classifier = nn.Sequential(
nn.Flatten(),
nn.Linear(512 * 7 * 7, 4096),
nn.ReLU(True),
nn.Dropout(),
nn.Linear(4096, 4096),
nn.ReLU(True),
nn.Linear(4096, num_classes)
)
def forward(self, x):
return self.classifier(self.features(x))
2. DenseNet Bottleneck
DenseNet은 이전 층의 출력값을 현재 층의 입력값과 결합(Concatenate)하여 정보 흐름을 극대화합니다.
import torch
import torch.nn.functional as F
class DenseBlockUnit(nn.Module):
def __init__(self, in_channels, growth_rate):
super().__init__()
inter_c = 4 * growth_rate
self.conv1 = nn.Conv2d(in_channels, inter_c, 1, bias=False)
self.conv2 = nn.Conv2d(inter_c, growth_rate, 3, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(in_channels)
self.bn2 = nn.BatchNorm2d(inter_c)
def forward(self, x):
out = self.conv1(F.relu(self.bn1(x)))
out = self.conv2(F.relu(self.bn2(out)))
return torch.cat([x, out], 1)
3. Inception 모듈 (InceptionV1)
서로 다른 크기의 필터를 병렬로 적용하여 다중 스케일 특징을 동시에 학습합니다.
class InceptionModule(nn.Module):
def __init__(self, in_c, f1, f3_red, f3, f5_red, f5, pool_proj):
super().__init__()
self.b1 = nn.Conv2d(in_c, f1, 1)
self.b2 = nn.Sequential(nn.Conv2d(in_c, f3_red, 1), nn.Conv2d(f3_red, f3, 3, padding=1))
self.b3 = nn.Sequential(nn.Conv2d(in_c, f5_red, 1), nn.Conv2d(f5_red, f5, 5, padding=2))
self.b4 = nn.Sequential(nn.MaxPool2d(3, 1, 1), nn.Conv2d(in_c, pool_proj, 1))
def forward(self, x):
return torch.cat([self.b1(x), self.b2(x), self.b3(x), self.b4(x)], 1)
4. ResNet Bottleneck
잔차 학습(Residual Learning)을 통해 깊은 네트워크에서도 학습이 원활하도록 돕습니다.
class ResBottleneck(nn.Module):
def __init__(self, in_dim, out_dim, stride=1):
super().__init__()
self.residual = nn.Sequential(
nn.Conv2d(in_dim, in_dim, 1, bias=False),
nn.BatchNorm2d(in_dim), nn.ReLU(),
nn.Conv2d(in_dim, in_dim, 3, stride, 1, bias=False),
nn.BatchNorm2d(in_dim), nn.ReLU(),
nn.Conv2d(in_dim, out_dim, 1, bias=False),
nn.BatchNorm2d(out_dim)
)
self.shortcut = nn.Sequential(nn.Conv2d(in_dim, out_dim, 1, stride), nn.BatchNorm2d(out_dim))
self.relu = nn.ReLU()
def forward(self, x):
return self.relu(self.residual(x) + self.shortcut(x))