VGG-16, VGG-19 Tensorflow 구현
VGGNet의 구조
1. 가장 기본 적인 구조로 모든 conv필터가 3x3이다.
매우 간단한 구조를 가지면서 꽤 좋은 성능을 보이기 때문에 비교군으로 혹은 테스트를 할때 애용된다.
2. vgg는 블럭형태가 반복되면서 들어가는 것을 확인 할 수 있다.
두개혹은 세개의 conv필터와 maxpooling을 블럭단위로 연속해서 쌓는 방식으로 진행된다.
블럭을 지날수록 필터의 크기는 반으로 줄어들게 한다. (conv필터는 padding = same을 하지만 maxpooling에 의하여 줄어듦)
Tensorflow 구현
cifar-10을 활용하여 vgg를 구현한뒤 테스트 해봤다.
데이터 로드부분은 생략하고 바로 코드 블럭을 구현한다.
vgg 블럭 구현
def build_vgg_block(input_layer,
num_cnn=3,
channel=64,
block_num=1,
):
# 입력 레이어
x = input_layer
# num_cnn : 한블럭에서 사용할 conv필터 개수 네트워크에 따라 2개일때가 있고 3개일때가 있음.
# CNN 레이어
for cnn_num in range(num_cnn):
x = keras.layers.Conv2D(
filters=channel,
kernel_size=(3,3),
activation='relu',
kernel_initializer='he_normal',
padding='same',
name=f'block{block_num}_conv{cnn_num}'
)(x)
# Max Pooling 레이어
x = keras.layers.MaxPooling2D(
pool_size=(2, 2),
strides=2,
name=f'block{block_num}_pooling'
)(x)
return x
구조는 간단하며 conv필터를 num_cnn개수만큼 쌓은뒤 maxpooling을 뒤에 쌓아서 한 블럭을 만든다.
default옵션으로 했을 경우 아래와 같다.
블럭을 만들었으면 블럭을 불러올 함수가 필요하다.
vgg builder 구현
def build_vgg(input_shape=(32,32,3),
num_cnn_list=[2,2,3,3,3],
channel_list=[64,128,256,512,512],
num_classes=10):
assert len(num_cnn_list) == len(channel_list) #모델을 만들기 전에 config list들이 같은 길이인지 확인합니다.
input_layer = keras.layers.Input(shape=input_shape) # input layer를 만들어둡니다.
output = input_layer
# config list들의 길이만큼 반복해서 블록을 생성합니다.
for i, (num_cnn, channel) in enumerate(zip(num_cnn_list, channel_list)):
output = build_vgg_block(
output,
num_cnn=num_cnn,
channel=channel,
block_num=i
)
output = keras.layers.Flatten(name='flatten')(output)
output = keras.layers.Dense(4096, activation='relu', name='fc1')(output)
output = keras.layers.Dense(4096, activation='relu', name='fc2')(output)
output = keras.layers.Dense(num_classes, activation='softmax', name='predictions')(output)
model = keras.Model(
inputs=input_layer,
outputs=output
)
return model
num_classes는 10으로 cifar-10 데이터셋을 사용했기 떄문이다. (다른 분류를 한다면 숫자를 클래스에 맞게 변경해주면된다.)
Input layer - vgg block - classification layer 순으로 배치를 하면 vgg완성이다.
vgg-19로 만들고 싶으면 builder의 파라미터만 변경해주면 된다.
vgg_19 = build_vgg(
num_cnn_list=[2,2,4,4,4],
channel_list=[64,128,256,512,512]
)
Result
20에폭으로 학습을 진행한다.
vgg_16.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.SGD(lr=0.01, clipnorm=1.),
metrics=['accuracy'],
)
history_16 = vgg_16.fit(
ds_train,
steps_per_epoch=int(ds_info.splits['train'].num_examples/BATCH_SIZE),
validation_steps=int(ds_info.splits['test'].num_examples/BATCH_SIZE),
epochs=EPOCH,
validation_data=ds_test,
verbose=1,
use_multiprocessing=True,
)
vgg_19.compile(
loss='sparse_categorical_crossentropy',
optimizer=tf.keras.optimizers.SGD(lr=0.01, clipnorm=1.),
metrics=['accuracy'],
)
history_19 = vgg_19.fit(
ds_train,
steps_per_epoch=int(ds_info.splits['train'].num_examples/BATCH_SIZE),
validation_steps=int(ds_info.splits['test'].num_examples/BATCH_SIZE),
epochs=EPOCH,
validation_data=ds_test,
verbose=1,
use_multiprocessing=True,
)
20에폭정도 했을때 loss가 정상적으로 잘 줄어들며 validation set으로 테스트 정확도 역시 증가하는 모습을 보여준다.
숙제
# 파이토치로도 구현 해보기