VGGNet
VGGNet은 카렌 시모니안(Karen Simonyan)과 앤드류 지서만(Andrew Zisserman)이 2015 ICLR에 게재한 “Very deep convolutional networks for large-scale image recognition” 논문에서 처음 발표했습니다. VGGNet은 합성곱층의 파라미터 수를 줄이고 훈련 시간을 개선하려고 탄생했습니다. 즉, 네트워크를 깊게 만드는 것이 성능에 어떤 영향을 미치는지 확인하고자 나온 것이 VGG입니다. VGG 연구 팀은 깊이의 영향만 최대한 확인하고자 합성곱층에서 사용하는 필터/커널의 크기를 가장 작은 3×3으로 고정했습니다.
네트워크 계층의 총 개수에 따라 여러 유형의 VGGNet(VGG16, VGG19 등)이 있으며, 이 중 VGG16 네트워크의 구조적 세부 사항은 다음 그림과 같습니다.
VGG16에는 파라미터가 총 1억 3300만 개 있습니다. 여기에서 주목할 점은 모든 합성곱 커널의 크기는 3×3, 최대 풀링 커널의 크기는 2×2이며, 스트라이드는 2라는 것입니다. 결과적으로
64개의 224×224 특성 맵(224×224×64)들이 생성됩니다. 또한, 마지막 16번째 계층을 제외하고는 모두 ReLU 활성화 함수가 적용됩니다.
계층 유형 | 특성 맵 | 크기 | 커널 크기 | 스트라이드 | 활성화 함수 |
이미지 | 1 | 224×224 | - | - | - |
합성곱층 | 64 | 224×224 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 64 | 224×224 | 3×3 | 1 | 렐루(ReLU) |
최대 풀링층 | 64 | 112×112 | 2×2 | 2 | - |
합성곱층 | 128 | 112×112 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 128 | 112×112 | 3×3 | 1 | 렐루(ReLU) |
최대 풀링층 | 128 | 56×56 | 2×2 | 2 | - |
합성곱층 | 256 | 56×56 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 256 | 56×56 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 256 | 56×56 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 256 | 56×56 | 3×3 | 1 | 렐루(ReLU) |
최대 풀링층 | 256 | 28×28 | 2×2 | 2 | - |
합성곱층 | 512 | 28×28 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 28×28 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 28×28 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 28×28 | 3×3 | 1 | 렐루(ReLU) |
최대 풀링층 | 512 | 14×14 | 2×2 | 2 | - |
합성곱층 | 512 | 14×14 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 14×14 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 14×14 | 3×3 | 1 | 렐루(ReLU) |
합성곱층 | 512 | 14×14 | 3×3 | 1 | 렐루(ReLU) |
최대 풀링층 | 512 | 7×7 | 2×2 | 2 | - |
완전연결층 | - | 4096 | - | - | 렐루(ReLU) |
완전연결층 | - | 4096 | - | - | 렐루(ReLU) |
완전연결층 | - | 1000 | - | - | 소프트맥스(softmax) |
필요한 라이브러리 호출
import copy ------ ①
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
import torch.utils.data as data
import torchvision
import torchvision.transforms as transforms
import torchvision.datasets as Datasets
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
VGG 모델 정의
class VGG(nn.Module):
def __init__(self, features, output_dim):
super().__init__()
self.features = features ------ VGG 모델에 대한 매개변수에서 받아 온 features 값을 self.features에 넣어 줍니다.
self.avgpool = nn.AdaptiveAvgPool2d(7)
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, output_dim)
) ------ 완전연결층과 출력층 정의
def forward(self, x):
x = self.features(x)
x = self.avgpool(x)
h = x.view(x.shape[0], -1)
x = self.classifier(h)
return x, h
모델 유형 정의
VGG11, VGG13, VGG16, VGG19 모델의 계층을 정리한 것입니다. 숫자(output channel, 출력 채널)는 Conv2d를 수행하라는 의미이며, 출력 채널(output channel)이 다음 계층의 입력 채널(input channel)이 됩니다. 또한, M은 최대 풀링(max pooling)을 수행하라는 의미입니다.
vgg11_config = [64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'] ------ 8(합성곱층) + 3(풀링층) = 11(전체 계층) = VGG11
vgg13_config = [64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'] ------ 10(합성곱층) + 3(풀링층) = 13(전체 계층) = VGG13
vgg16_config = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 'M', 512, 512, 512, 'M', 512, 512, 512, 'M'] ------ 13(합성곱층) + 3(풀링층) = 16(전체 계층) = VGG16
vgg19_config = [64, 64, 'M', 128, 128, 'M', 256, 256, 256, 256, 'M', 512, 512, 512, 512, 'M', 512, 512, 512, 512, 'M'] ------ 16(합성곱층) + 3(풀링층) = 19(전체 계층) = VGG19
VGG11, VGG13, VGG16, VGG19에 대한 네트워크를 그림으로 정리하면 다음과 같습니다.
VGG 계층 정의
VGG 모델에서 네트워크를 정의합니다. 네트워크는 vgg11_config를 사용합니다.
def get_vgg_layers(config, batch_norm):
layers = []
in_channels = 3
for c in config: ------ vgg11_config 값들을 가져옵니다.
assert c == 'M' or isinstance(c, int) ------ ①
if c == 'M': ------ 불러온 값이 ‘M’이면 최대 풀링(MaxPool2d)을 적용
layers += [nn.MaxPool2d(kernel_size = 2)]
else: ------ 불러온 값이 숫자이면 합성곱(Conv2d) 적용
conv2d = nn.Conv2d(in_channels, c, kernel_size=3, padding=1)
if batch_norm: ------ 배치 정규화(batch normalization)를 적용할지에 대한 코드
layers += [conv2d, nn.BatchNorm2d(c), nn.ReLU(inplace=True)] ------ 배치 정규화가 적용될 경우 배치 정규화+ReLU 적용
else:
layers += [conv2d, nn.ReLU(inplace=True)] ------ 배치 정규화가 적용되지 않을 경우 ReLU만 적용
in_channels = c
return nn.Sequential(*layers) ------ 네트워크의 모든 계층을 반환
① 조건문을 정의합니다.
ⓐ 가정 설정문이라고 불리는 assert는 뒤의 조건이 True가 아니면 에러를 발생시킵니다. 따라서 c == 'M'이 아니면 오류가 발생합니다. 예를 들어 다음과 같습니다.
a = 1
assert a == 11
조건이 True가 아니기 때문에 다음과 같은 오류가 발생합니다.
---------------------------------------------------------------------------
AssertionError Traceback (most recent call last)
<ipython-input-1-b211624433f8> in <module>
1 a = 1
----> 2 assert a == 11
AssertionError:
ⓑ isinstance는 주어진 조건이 True인지 판단합니다. 예를 들어 다음과 같이 사용합니다.
print(isinstance(1, int)) ------ 1이 integer인지 판단
print(isinstance(1.2, int)) ------ 1.2가 integer인지 판단
print(isinstance('deep learning', str)) ------ deep learning이 string인지 판단
다음은 isinstance로 조건이 True/False인지 확인한 결과입니다.
True
False
True
따라서 assert c == 'M' or isinstance(c, int) 의미는 c가 'M'이 아니거나 int가 아니라면 오류가 발생합니다.
get_vgg_layers() 함수를 호출하여 모델의 계층을 생성합니다. 이때 배치 정규화(batch normalization)에 대한 계층도 추가합니다.
모델 계층 생성
vgg11_layers = get_vgg_layers(vgg11_config, batch_norm=True) ------ ①
① batch_norm(Batch Normalization)은 데이터의 평균을 0으로, 표준편차를 1로 분포시키는 것입니다. 각 계층에서 입력 데이터의 분포는 앞 계층에서 업데이트된 가중치에 따라 변합니다. 즉, 각 계층마다 변화되는 분포는 학습 속도를 늦출 뿐만 아니라 학습도 어렵게 합니다. 따라서 각 계층의 입력에 대한 분산을 평균 0, 표준편차 1로 분포시키는 것이 batch_norm(배치 정규화)입니다.
VGG11 전체에 대한 네트워크
OUTPUT_DIM = 2 ------ 개와 고양이 두 개의 클래스 사용
model = VGG(vgg11_layers, OUTPUT_DIM)
print(model)
다음은 VGG11 전체에 대한 네트워크를 출력한 결과입니다.
VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(2): ReLU(inplace=True)
(3): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(4): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(5): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(6): ReLU(inplace=True)
(7): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(8): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(9): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(10): ReLU(inplace=True)
(11): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(12): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(13): ReLU(inplace=True)
(14): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(15): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(16): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(17): ReLU(inplace=True)
(18): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(19): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(20): ReLU(inplace=True)
(21): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(22): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(23): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(24): ReLU(inplace=True)
(25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(26): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(27): ReLU(inplace=True)
(28): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=7)
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=2, bias=True)
)
)
VGG11 사전 훈련된 모델 사용
import torchvision.models as models
pretrained_model = models.vgg11_bn(pretrained=True) ------ ①
print(pretrained_model)
① 배치 정규화가 적용된 사전 훈련된 VGG11 모델을 사용하기 위해서는 다음과 같은 파라미터를 사용합니다.
ⓐ vgg11_bn은 VGG11 기본 모델에 배치 정규화가 적용된 모델을 사용하겠다는 의미입니다.
ⓑ pretrained를 True로 설정하면 사전 훈련된 모델을 사용(미리 학습된 파라미터 값들을 사용)하겠다는 의미입니다.
'영상처리 > 기초' 카테고리의 다른 글
Vision Transformer(ViT) 리뷰 (16) | 2023.02.26 |
---|---|
GAN(Generative Adversarial Networks) (92) | 2023.02.15 |
ResNet 리뷰 (10) | 2023.01.24 |
Python slowfast설치 windows환경 (23) | 2023.01.20 |
Instance Segmentation MASK R-CNN (13) | 2023.01.07 |