: CNN 모델의 조상 격.
구조는 다음과 같다
Input / 3개의 Convolution layer(C1, C3, C5) / 2개의 subsampling layer(S2, S4) / 1층의 fully-connected layer(F6) / Output으로 구성
< VGGNet 구조 특징 >
- C1 ~ F6까지 tanh 활성함수 사용한 것이 특징
- subsampling 으로 Average Pooling 사용
- 총 파라미터 60,000개
C.L : (가중치입력맵개수 + 바이어스)특성맵개수
S.L : (가중치 + 바이어스)*특성맵개수
: input image size를 (256*256)으로 고정시켜줌 (추후 FC layer의 입력 크기가 고정되어야 하기 때문)
구조는 다음과 같다.
Input / 5개의 C.L / 3개의 P.L / 2개의 N.L / 2개의 FC layer / Output으로 구성
🎈 < AlexNet 구조 특징 >
- Max Pooling 기법 사용
- ReLU Nonlinearity
: 학습속도가 sigmoid, tanh에 비해 몇배 빠름
- Training on Multiple GPUs
: 네트워크를 2개의 GPU로 나누어 학습 진행 >> GPU parallelization이라 부름.
(독립적인 학습도 가능하고 하나의 layer에서만 GPU를 통합하는 것도 가능)
- LRN을 사용한 Normalization Layer.
🎈 LRN (Local Response Normalization) 이란 ?
: generalization을 목적으로 함. ReLU는 non-saturation nonlinearity 함수이므로 입력 normalization을 필요로 하지 않기에 이를 예방하기 위해 등장한 함수
측면 억제의 형태로 구현됨.
- Overlapping Pooling
: max pooling을 할 때 중복 되지 않는 영역만 pooling을 진행하지만, AlexNet은 겹치는 부분이 있도록 Pooling 진행해 오버피팅 개선추가 사항 3X3 Convolution filter 활용
🎈 Reducing Overfitting
AlexNet의 경우 약 6천만 개의 Parameter가 존재해 오버피팅 없이 학습이 어려울 정도이다. 이를 방지하고자 두 가지 방안을 제안한다.
- Data Augmentation
: 현재 갖고 있는 데이터를 좀 더 다양하게 만들어 CNN 모델을 학습하기 위해 만들어진 개념, 연산량이 매우 적고 CPU 내에서 이루어지기에 계산 비용 X (좌우 반전, 이미지를 다르게 잘라 여러 이미지 생성 등)
- Dropout
detail
momentum = 0.9, batch_size = 128, weight_decay = 0.005
weight ~ 가우시안 분포(0, 0.01^2)
bias 초기화 : C2, C4, C5와 FC1에선 1로, 나머진 0으로 초기화
learning rate : 0.01weight decay ?
: 데이터는 단순한데 모델이 복잡하면 weight는 값이 점점 커지게 되면서 overfitting이 발생한다. 이를 방지하고자 weight 값 증가하는 것을 제한하며 모델 복잡도를 감소시킴으로 제한하는 기법.
논문 참고 : "Return of the Devil in the Details: Delving Deep into Convolutional Nets"
각 모델은 속도와 정확도 사이의 trade-off를 고려한 모델이다.
5개의 Conv layer, 3개의 FC layer로 구성
- VGG-F
: 빠른 속도에 초점을 맞춘 모델
filter(kernel) size를 크게 하고 stride를 크게 함으로써 연산량을 줄였다. (1번째 레이어)- VGG-M
속도, 정확도 중간
(2번째 레이어에서 VGG-S보다 보폭을 1더 크게함으로써 연산량 줄이고 정확도를 낮춤)- VGG-S
: 느리지만 정확도에 초점을 맞춘 모델
: 옥스포드 대학의 연구팀에 의해 개발된 모델
네트워크가 깊어짐에 따라(층이 많을수록) 어떤 영향을 미치는지 알고자 진행
16 ~ 19개의 층으로 구성된 모델을 의미하며 VGG16, VGG19로 불림
< VGGNet 구조 예시 >
0) 인풋: 224 x 224 x 3 이미지(224 x 224 RGB 이미지)를 입력받을 수 있다.
1) 1층(conv1_1): 64개의 3 x 3 x 3 필터커널로 입력이미지를 컨볼루션해준다. zero padding은 1만큼 해줬고, 컨볼루션 보폭(stride)는 1로 설정해준다. zero padding과 컨볼루션 stride에 대한 설정은 모든 컨볼루션층에서 모두 동일하니 다음 층부터는 설명을 생략하겠다. 결과적으로 64장의 224 x 224 특성맵(224 x 224 x 64)들이 생성된다. 활성화시키기 위해 ReLU 함수가 적용된다. ReLU함수는 마지막 16층을 제외하고는 항상 적용되니 이 또한 다음 층부터는 설명을 생략하겠다.
2) 2층(conv1_2): 64개의 3 x 3 x 64 필터커널로 특성맵을 컨볼루션해준다. 결과적으로 64장의 224 x 224 특성맵들(224 x 224 x 64)이 생성된다. 그 다음에 2 x 2 최대 풀링을 stride 2로 적용함으로 특성맵의 사이즈를 112 x 112 x 64로 줄인다.
*conv1_1, conv1_2와 conv2_1, conv2_2등으로 표현한 이유는 해상도를 줄여주는 최대 풀링 전까지의 층들을 한 모듈로 볼 수 있기 때문이다.
3) 3층(conv2_1): 128개의 3 x 3 x 64 필터커널로 특성맵을 컨볼루션해준다. 결과적으로 128장의 112 x 112 특성맵들(112 x 112 x 128)이 산출된다.
4) 4층(conv2_2): 128개의 3 x 3 x 128 필터커널로 특성맵을 컨볼루션해준다. 결과적으로 128장의 112 x 112 특성맵들(112 x 112 x 128)이 산출된다. 그 다음에 2 x 2 최대 풀링을 stride 2로 적용해준다. 특성맵의 사이즈가 56 x 56 x 128로 줄어들었다.
5) 5층(conv3_1): 256개의 3 x 3 x 128 필터커널로 특성맵을 컨볼루션한다. 결과적으로 256장의 56 x 56 특성맵들(56 x 56 x 256)이 생성된다.
6) 6층(conv3_2): 256개의 3 x 3 x 256 필터커널로 특성맵을 컨볼루션한다. 결과적으로 256장의 56 x 56 특성맵들(56 x 56 x 256)이 생성된다.
7) 7층(conv3_3): 256개의 3 x 3 x 256 필터커널로 특성맵을 컨볼루션한다. 결과적으로 256장의 56 x 56 특성맵들(56 x 56 x 256)이 생성된다. 그 다음에 2 x 2 최대 풀링을 stride 2로 적용한다. 특성맵의 사이즈가 28 x 28 x 256으로 줄어들었다.
8) 8층(conv4_1): 512개의 3 x 3 x 256 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 28 x 28 특성맵들(28 x 28 x 512)이 생성된다.
9) 9층(conv4_2): 512개의 3 x 3 x 512 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 28 x 28 특성맵들(28 x 28 x 512)이 생성된다.
10) 10층(conv4_3): 512개의 3 x 3 x 512 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 28 x 28 특성맵들(28 x 28 x 512)이 생성된다. 그 다음에 2 x 2 최대 풀링을 stride 2로 적용한다. 특성맵의 사이즈가 14 x 14 x 512로 줄어든다.
11) 11층(conv5_1): 512개의 3 x 3 x 512 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 14 x 14 특성맵들(14 x 14 x 512)이 생성된다.
12) 12층(conv5_2): 512개의 3 x 3 x 512 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 14 x 14 특성맵들(14 x 14 x 512)이 생성된다.
13) 13층(conv5-3): 512개의 3 x 3 x 512 필터커널로 특성맵을 컨볼루션한다. 결과적으로 512장의 14 x 14 특성맵들(14 x 14 x 512)이 생성된다. 그 다음에 2 x 2 최대 풀링을 stride 2로 적용한다. 특성맵의 사이즈가 7 x 7 x 512로 줄어든다.
14) 14층(fc1): 7 x 7 x 512의 특성맵을 flatten 해준다. flatten이라는 것은 전 층의 출력을 받아서 단순히 1차원의 벡터로 펼쳐주는 것을 의미한다. 결과적으로 7 x 7 x 512 = 25088개의 뉴런이 되고, fc1층의 4096개의 뉴런과 fully connected 된다. 훈련시 dropout이 적용된다.
15) 15층(fc2): 4096개의 뉴런으로 구성해준다. fc1층의 4096개의 뉴런과 fully connected 된다. 훈련시 dropout이 적용된다.
16) 16층(fc3): 1000개의 뉴런으로 구성된다. fc2층의 4096개의 뉴런과 fully connected된다. 출력값들은 softmax 함수로 활성화된다. 1000개의 뉴런으로 구성되었다는 것은 1000개의 클래스로 분류하는 목적으로 만들어진 네트워크란 뜻이다.
🎈 < VGGNet 특징 >
- 라이브러리 불러오기
import torch #신경망들 포함 import torch.nn as nn #최적화 알고리즘 포함 import torch.optim as optim #텐서에 초기값 부여 import torch.nn.init as init #이미지 데이터셋 집합체 import torchvision.datasets as datasets #이미지 변환 툴 import torchvision.transforms as transforms #학습 및 배치로 모델에 넣어주기 위한 툴 from torch.utils.data import DataLoader import torch.utils.model_zoo as0 model_zoo import numpy as np import matplotlib.pyplot as plt
- model url
__all__ = { 'VGG', 'vgg11', 'vgg11_bn', 'vgg13', 'vgg13_bn', 'vgg16', 'vgg16_bn', 'vgg19_bn', 'vgg19'} model_urls = { 'vgg11': 'https://download.pytorch.org/models/vgg11-bbd30ac9.pth', 'vgg13': 'https://download.pytorch.org/models/vgg13-c768596a.pth', 'vgg16': 'https://download.pytorch.org/models/vgg16-397923af.pth', 'vgg19': 'https://download.pytorch.org/models/vgg19-dcbb9e9d.pth', 'vgg11_bn': 'https://download.pytorch.org/models/vgg11_bn-6002323d.pth', 'vgg13_bn': 'https://download.pytorch.org/models/vgg13_bn-abd245e5.pth', 'vgg16_bn': 'https://download.pytorch.org/models/vgg16_bn-6c64b313.pth', 'vgg19_bn': 'https://download.pytorch.org/models/vgg19_bn-c79401a0.pth', }
- VGG class 생성
input : features, num_class, init_weights
classifier : fc layer들
features : 쌓아가야 할 VGG-net의 convolution layer
kaiming_nomalization을 통해 weight 초기화
cf> VGG net에서는 bias 값이 항상 0이다.class VGG(nn.Module): def __init__(self, features, num_classes = 1000, init_weights = True): super(VGG, self).__init__() self.features = features #Convolution self.avgpool = nn.AdaptiveAvgPool2d((7, 7)) self.classifier = nn.Sequential( nn.Linear(512 * 7 * 7, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, 4096), nn.ReLU(True), nn.Dropout(), nn.Linear(4096, num_classes), ) if init_weights: self._initialize_weights() def forward(self, x): x = self.features(x) x = self.avgpool(x) x = x.view(x.size(0), -1) x = self.classifier(x) return x def _initialize_weights(self): for m in self.modules(): if isinstance(m, nn.Conv2d): nn.init.kaiming_normal_(m.weight, mode = 'fan_out', nonlinearity = 'relu') if m.bias is not None: nn.init.constant_(m.bias, 0) elif isinstance(m, nn.BatchNorm2d): nn.init.constant_(m.weight, 1) nn.init.constant_(m.bias, 0) elif isinstance(m, nn.Linear): nn.init.normal_(m.weight, 0, 0.01) nn.init.constant(m.bias, 0)
- " features 값을 어떻게 넣어줄 수 있는가 "
make_layer : CFG에 맞춰 make_layer 동작
CFG : network 구성 역할
cf> in_channels를 v로 바꿔주는 이유
: convolution layer를 통과하고 나오면 batch_size는 그대로지만 channel 수는 변하게 됨. 다음 channel에서 변경된 수 만큼의 channel을 받아야 하므로 in_channel을 그만큼 바꿔주게 됨def make_layers(cfg, batch_norm = False): layers = [] in_channels = 3 for v in cfg: if v == 'M': layers += [nn.MaxPool2d(kernel_size = 2, stride = 2)] else: conv2d = nn.Conv2d(in_channels, v, kernel_size = 3, padding = 1) if batch_norm: layers += [conv2d, nn.BatchNorm2d(v), nn.ReLU(inplace=True)] else: layers += [conv2d, nn.ReLU(inplace=True)] return nn.Sequential(*layers) cfg = { 'A':[64, 'M', 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'B':[64, 64, 'M', 128, 128, 'M', 256, 256, 'M', 512, 512, 'M', 512, 512, 'M'], 'D':[64, 64, 'M', 128, 128, 'M', 256,256,256, 'M', 512,512,512,'M',512,512,512,'M'], 'E':[64,64,'M',128,128,'M',256,256,256,256,'M',512,512,512,512,'M',512,512,512,512,'M'], 'custom':[64,64,64,'M',128,128,128,'M',256,256,256,'M'] }
- 🎈 VGG 모델 생성
feature : make_layer를 통해 내가 원하는 대로 생성 가능
num_class : CIFAR10의 경우, 클래스가 10개이므로 10으로 설정
+) CFG에서 custom layer를 추가한 경우, VGG class의 in_feature가 달라지므로 수정해줘야 함
-> image size가 다른 상태에서 VGG-net을 적용하고자 하면 VGG class에서 nn.Linear() 수정해주기CNN = VGG(make_layers(cfg['custom']), num_classes = 10, init_weights=True) CNN