You're able to check Reference
합성곱 기반, 레이어를 16개 쌓은 것이다. 이전에 학습을 했던 기억을 가져와 새로운 표본에서 특징을 추출하는 방식이다.
특징 추출과 미세 조정을 한다.
필터로 3x3 Convolution을 쓰는데, VGG16의 처리 과정은 하기와 같다.
count | process | result |
---|---|---|
1 | 3x3 conv 3x3 conv | 64 |
Maxpool | ||
2 | 3x3 conv 3x3 conv | 128 |
Maxpool | ||
3 | 3x3 conv 3x3 conv | 256 |
Maxpool | ||
4 | 3x3 conv 3x3 conv | 512 |
Maxpool | ||
Flatten | ||
Dense | 4096 | |
Dense | 1000 |
1x1 은 실제로 무시된다.
eg. 224 x 224 x 3(컬러)의 이미지가 있다고 한다.
→ conv 3 x 3 (필터) → 1 pixel이 가지는 의미 : 이전 레이어의 3x3
3x3 → 1x1
5x5 → 3x3 → 1x1 (한 픽셀에 5x5의 정보를 담고 있다.)
Maxpool 을 거치면 112x112 의 절반 크기로 된다 → 3x3 conv 필터로 된 1픽셀은 2x2 의 원본 정보를 담고 있다. 그렇다면 3x3은 6x6인 셈이다.
……? 뭐 … 이해는 어려운데…………..하다 보면 되겠지…
import tensorflow as tf
import numpy as np
import keras
# mnist 데이터셋 로드
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
# 값의 범위를 0~1로 정규화
x_train, x_test = x_train / 255.0, x_test / 255.0
# 텐서플로우에서는 이미지일 경우, 맨 마지막 디멘션이 흑백일 경우 1, 컬러일 경우 3 !
# x_train : (60000,28,28) -> x_train.shape 을 통해 확인 !
# axis = -1 : 맨 뒤에 차원 하나 추가 ! axis = 0 : 맨 앞에 차원 하나 추가 !
x_train = np.expand_dims(x_train, axis = -1)
x_test = np.expand_dims(x_test, axis = -1)
# 1. 입력 레이어 생성
input = tf.keras.layers.Input(shape =(28, 28, 1)) # mnist : 28 x 28, 흑백 : 1
output = tf.keras.layers.Dense(10, activation='softmax')(input) # Dense의 입력
model = tf.keras.models.Model(input, output)
print(x_train.shape)
print(x_test.shape)
> (60000, 28, 28, 1)
(10000, 28, 28, 1)
# VGGNet은 3x3 필터를 64개 씀!
vgg_block01 = tf.keras.layers.Conv2D(64,(3,3),padding='SAME',activation = 'relu')(input)
vgg_block01 = tf.keras.layers.Conv2D(64,(3,3),padding='SAME',activation = 'relu')(vgg_block01)
# Maxpool로 인해 이미지 크기가 절반으로 ! -> 14x14x64
vgg_block01 = tf.keras.layers.MaxPool2D((2,2))(vgg_block01) # conv 64개를 이용한게 2번 사용 되었다.
# 8x8x128
vgg_block02 = tf.keras.layers.Conv2D(128,(3,3),padding = 'SAME', activation = 'relu')(vgg_block01)
vgg_block02 = tf.keras.layers.Conv2D(128,(3,3),padding = 'SAME', activation = 'relu')(vgg_block02)
vgg_block02 = tf.keras.layers.MaxPool2D((2,2))(vgg_block02)
# 4x4x256
vgg_block03 = tf.keras.layers.Conv2D(256,(3,3),padding = 'SAME', activation = 'relu')(vgg_block02)
vgg_block03 = tf.keras.layers.Conv2D(256,(3,3),padding = 'SAME', activation = 'relu')(vgg_block03)
vgg_block03 = tf.keras.layers.Conv2D(256,(3,3),padding = 'SAME', activation = 'relu')(vgg_block03)
vgg_block03 = tf.keras.layers.MaxPool2D((2,2))(vgg_block03)
# 2x2x512
vgg_block04 = tf.keras.layers.Conv2D(512,(3,3),padding = 'SAME', activation = 'relu')(vgg_block03)
vgg_block04 = tf.keras.layers.Conv2D(512,(3,3),padding = 'SAME', activation = 'relu')(vgg_block04)
vgg_block04 = tf.keras.layers.Conv2D(512,(3,3),padding = 'SAME', activation = 'relu')(vgg_block04)
vgg_block04 = tf.keras.layers.MaxPool2D((2,2))(vgg_block04)
# 2048
flatten = tf.keras.layers.Flatten()(vgg_block04)