VGGNet16 논문리뷰

Hyewon Jung·2023년 5월 19일

딥러닝 모델 리뷰

목록 보기
3/3

0. 목차

  1. 모델 개요
  2. 모델 구조
  3. 모델의 장점과 단점
  4. 코드 리뷰



1. 모델 개요

cnn의 깊이가 깊어지면 어떤일이 발생하는지를 중점으로 모델을 쌓았다. 3x3의 아주 작은 conv layer을 사용하였고 이 conv layer가 16층, 19층을 쌓으면 좋은 성능을 낼 수 있다고 생각하였고 이를 구현한 모델이다. 16층이나 19층처럼 층을 깊게 쌓으면 모든 데이터셋에 어느정도 일반화할 수 있는 성능을 가진다고 판단해 현재까지도 backbone으로 많이 사용된다.


2. 모델 구조

  • 13개의 conv layer + 3개의 FC layer
  • 3x3 conv filters
  • 1x1 strides
  • 1x1 padding
  • 2x2 max pooling(strides 2)
  • activation : ReLU
  • 전처리는 오직 trainset의 RGB값을 빼기만 하였다.

왜 3x3을 했는가?

  • 3x3을 2번 conv하는 것과 5x5로 1번 conv하는 건 동일 feature map을 반환한다.
  • 채널 수를 C라고 가정했을 때, VGGNet에서 3 × 3 필터를 사용한 이유는, 3 × 3 필터 3개를 쌓았을 경우에 총 27×C^2개의 가중치 파라미터를 갖고, 7 × 7 의 필터를 사용할 경우에 49×C^2의 가중치 파라미터 개수를 갖는다. 즉 연산량을 줄일 수 있다.
  • 1개의 큰 필터 레이어를 거치는 것보다, 3개의 작은 필터를 거치면서 ‘비선형성’을 증가시킬 수 있다

VGGNet16의 conv map은 빨간색 박스를 확인하면 된다.



3. 모델 장단점

장점단점
시간 단축이 가능하다파라미터수가 많다



4. 코드 리뷰

개인노션 VGGNet 코드 리뷰 파이토치

아래는 vggnet16의 텐서플로 코드이다. 다음과 같은 사항을 확인하면 좋을 듯 하다.

  1. 모델 구조는 하단 빨간 박스를 참고하였다.
  2. VGGNet에서 maxpooling의 사이즈와 stride는 2x2로 정해져있다.
  3. 모든 VGGNet에서 fclayer의 구조는 정해져있다.
  • maxpool - 4096size의 fc layer두개 - 1000size의 softmax
  • 1000size는 임의로 정한 것이며 이정도 사이즈면 특징을 잘 처리할 수 있을 것이라 기대하고 넣은 값이다.
  1. 모든 cnn이 그렇듯 fc layer에 넣기 전에 flatten을 해야 한다.
  2. dropout은 train할 때는 0.5, test할 때는 1로 변경해야 한다.
  3. optimizer는 Adam을 썼으며 loss는 구별할 게 여러개이므로 categorical_crossentropy를 사용하였다.

class VGG16(Sequential):
    def __init__(self, input_shape):
        super().__init__()

        self.add(Conv2D(64, kernel_size=(3,3), padding='same',
                        activation='relu', input_shape=input_shape))
        self.add(Conv2D(64, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))

        self.add(Conv2D(128, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(128, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2), strides= (2,2)))

        
        self.add(Conv2D(256, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(256, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(256, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))

        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))

        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(Conv2D(512, kernel_size=(3,3), padding='same',
                        activation='relu'))
        self.add(MaxPooling2D(pool_size=(2,2), strides=(2,2)))

        self.add(Flatten())
        self.add(Dense(4096, activation='relu'))
        self.add(Dropout(0.5))
        self.add(Dense(4096, activation='relu'))
        self.add(Dropout(0.5))
        self.add(Dense(1000, activation='softmax'))

        self.compile(optimizer=tf.keras.optimizers.Adam(0.003),
                     loss='categorical_crossentropy',
                     metrics=['accuracy'])
profile
Amateur data scientist & student

0개의 댓글