Custom ResNet
널리 알려진 ResNet 34,50,101 등과 같은 모델을 그대로 가져와서 fine-tuning 할 수도 있지만
다른 모델 구조로 실험하고 싶거나 기타 등등의 이유로 직접 구현이 필요한 경우도 존재한다.
resnet 뒤의 34,101과 같은 숫자는 모델 안의 컨볼루션 레이어의 개수이다.
레이어의 개수가 작을 때는 3x3 컨볼루션을 두 번 사용하고
레이어의 개수가 많으면 bottleneck 구조(1x1-3x3-1x1)를 사용한다.(계산 파라미터 수 감소)
resnet의 구조에는 batch normalization의 위치나 컨볼루션 레이어의 위치 등에 따라 구조가 미세하게 다른데,
저자는 full-pre activation구조가 일반적으로 성능이 좋다고 이야기한다.
아래는 full-pre activation 구조의 tensorflow 기반 resnet 구현 코드이다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import tensorflow as tf
from tensorflow.keras.layers import *
from tensorflow.keras.models import *
def res_identity(x, filters):
#full pre-activation
x_skip = x
f1, f2 = filters
x = BatchNormalization()(x)
x = ReLU()(x)
x = Conv2D(f1, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
x = BatchNormalization()(x)
x = ReLU()(x)
x = Conv2D(f2, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
x = Add()([x, x_skip])
return x
def res_conv(x, s, filters):
'''
here the input size changes'''
x_skip = x
f1, f2 = filters
# first block
x = BatchNormalization()(x)
x = ReLU()(x)
x = Conv2D(f1, kernel_size=(3, 3), strides=(s, s), padding='same')(x)
x = BatchNormalization()(x)
x = ReLU()(x)
x = Conv2D(f1, kernel_size=(3, 3), strides=(1, 1), padding='same')(x)
x_skip = Conv2D(f2, kernel_size=(1, 1), strides=(s, s), padding='same')(x_skip)
x = Add()([x, x_skip])
return x
실제로 256x256x3의 이미지를 받는 간단한 분류 모델을 아래와 같이 구현할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
def resnet22():
input_im = Input(shape=(256,256,3))
x = Conv2D(16, kernel_size=(3, 3), strides=2, padding='same')(input_im)
x = BatchNormalization()(x)
x = ReLU()(x)
x = res_conv(x, s=2, filters=(16, 16))
x = res_identity(x, filters=(16, 16))
x = res_conv(x, s=2, filters=(32, 32))
x = res_identity(x, filters=(32, 32))
x = res_conv(x, s=2, filters=(64, 64))
x = res_identity(x, filters=(64, 64))
x = res_conv(x, s=2, filters=(128, 128))
x = res_identity(x, filters=(128, 128))
# 여기에 conv layer 추가해도 됨.
x = Flatten()(x)
x = Dense(128, activation='relu')(x)
x = Dense(4, activation='softmax')(x)
model = Model(inputs=input_im, outputs=x)
return model
model = resnet22()
댓글남기기