pytorch & tensorflow

VGG-16, VGG-19 Tensorflow 구현

OBJECT_FINALIZE 2021. 9. 29. 17:12

vgg 구조

VGGNet의 구조

1. 가장 기본 적인 구조로 모든 conv필터가 3x3이다.

 

매우 간단한 구조를 가지면서 꽤 좋은 성능을 보이기 때문에 비교군으로 혹은 테스트를 할때 애용된다.

 

2. vgg는 블럭형태가 반복되면서 들어가는 것을 확인 할 수 있다.

 

두개혹은 세개의 conv필터와 maxpooling을 블럭단위로 연속해서 쌓는 방식으로 진행된다.

 

블럭을 지날수록 필터의 크기는 반으로 줄어들게 한다. (conv필터는 padding = same을 하지만 maxpooling에 의하여 줄어듦)

 

vgg net 구조

 

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 block 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으로 테스트 정확도 역시 증가하는 모습을 보여준다.

 

 

숙제

# 파이토치로도 구현 해보기