• 카테고리

    질문 & 답변
  • 세부 분야

    컴퓨터 비전

  • 해결 여부

    미해결

Model API과 Keras.Application API input_tensor와의 동작 관계에 대해서 궁금합니다

21.07.14 10:23 작성 조회수 125

0

안녕하세요. 토이 프로젝트로 이미지 안의 text를 감지하는 모델 중 하나인 EAST에 대해서 코드 수행을 하려고 했는데

누군가 짜놓은 코드 기반으로 하다보니, 코드 내부에서 모델 구성하는 부분에서 궁금한 점이 있어서요!

모델의 시작은 resnet50 입력부터 시작하는 것 같습니다. 실제 summary에서도 그렇게 나오고, 이 출력은 Unet 기반으로 피처를 concat 하는 형태로 가져가서 마지막에 regression을 하게 됩니다

모델 resnet50 입력에 input_tensor 파라미터를 통해서 input_image라고 지정을 하게 되어서 shape는 아래 캡쳐한 것처럼 (None, None, None, 3)라고 나온 것 같습니다

그런데 코드 마지막에 최종 모델 API에서는 입력에

overly_small_text_region_training_mask, text_region_boundary_training_mask, target_score_map 

을 추가로 지정하는데, 해당 입력 텐서 3개는 전혀 모델 입력으로 들어가지 않는 것 아닌가요?

감사합니다

class EAST_model:
    def __init__(self, input_size=512):
        input_image = Input(shape=(None, None, 3), name='input_image')
        overly_small_text_region_training_mask = Input(shape=(None, None, 1), name='overly_small_text_region_training_mask')
        text_region_boundary_training_mask = Input(shape=(None, None, 1), name='text_region_boundary_training_mask')
        target_score_map = Input(shape=(None, None, 1), name='target_score_map')
        resnet = ResNet50(input_tensor=input_image, weights='imagenet', include_top=False, pooling=None)
        # print(resnet.summary())
        x = resnet.get_layer('conv5_block3_out').output

        x = Lambda(resize_bilinear, name='resize_1')(x)
        x = concatenate([x, resnet.get_layer('conv4_block6_out').output], axis=3)
        x = Conv2D(128, (1, 1), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)
        x = Conv2D(128, (3, 3), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)

        x = Lambda(resize_bilinear, name='resize_2')(x)
        x = concatenate([x, resnet.get_layer('conv3_block4_out').output], axis=3)
        x = Conv2D(64, (1, 1), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)
        x = Conv2D(64, (3, 3), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)

        x = Lambda(resize_bilinear, name='resize_3')(x)
        #x = concatenate([x, ZeroPadding2D(((1, 0),(1, 0)))(resnet.get_layer('conv2_block3_out').output)], axis=3)
        x = concatenate([x, resnet.get_layer('conv2_block3_out').output], axis=3)
        x = Conv2D(32, (1, 1), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)
        x = Conv2D(32, (3, 3), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)

        x = Conv2D(32, (3, 3), padding='same', kernel_regularizer=regularizers.l2(1e-5))(x)
        x = BatchNormalization(momentum=0.997, epsilon=1e-5, scale=True)(x)
        x = Activation('relu')(x)

        pred_score_map = Conv2D(1, (1, 1), activation=tf.nn.sigmoid, name='pred_score_map')(x)
        rbox_geo_map = Conv2D(4, (1, 1), activation=tf.nn.sigmoid, name='rbox_geo_map')(x) 
        rbox_geo_map = Lambda(lambda x: x * input_size)(rbox_geo_map)
        angle_map = Conv2D(1, (1, 1), activation=tf.nn.sigmoid, name='rbox_angle_map')(x)
        angle_map = Lambda(lambda x: (x - 0.5) * np.pi / 2)(angle_map)
        pred_geo_map = concatenate([rbox_geo_map, angle_map], axis=3, name='pred_geo_map')

        model = Model(inputs=[input_image, overly_small_text_region_training_mask, text_region_boundary_training_mask, target_score_map], outputs=[pred_score_map, pred_geo_map])

답변 1

답변을 작성해보세요.

0

유영재님의 프로필

유영재

질문자

2021.07.14

아, 다시 코드를 보니 loss 정의에서 위 3개 텐서가 사용하더라구요

model.compile(loss=[dice_loss(east.overly_small_text_region_training_mask, east.text_region_boundary_training_mask, score_map_loss_weight, small_text_weight),
                                 rbox_loss(east.overly_small_text_region_training_mask, east.text_region_boundary_training_mask, small_text_weight, east.target_score_map)],
                           loss_weights=[1., 1.],
                           optimizer=opt)

각 배치마다 저 3개의 값이 다르고, 이를 loss 때 계산 용도로 사용하려고 전달하는 것 같습니다. 실제 모델에서 사용하지 않지만, 저렇게 다른 용도를 위해서 Model.input 파라미터 입력으로 전달해주는 경우도 종종 있나요?

감사합니다 

네, 충분히 그런 경우가 있을 수 있습니다. 

감사합니다.