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


| 장점 | 단점 |
|---|---|
| 시간 단축이 가능하다 | 파라미터수가 많다 |
아래는 vggnet16의 텐서플로 코드이다. 다음과 같은 사항을 확인하면 좋을 듯 하다.

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'])