def model_v10(basemodel_name, model_image_size=(384, 512)):
    """ use conv output 7 column
    :param basemodel_name: string, one of 'resnet50', 'xception', 'inception_v3' or 'inception_resnet_v2'
    :param model_image_size: original size is 540(height)*720(width)
    :return: keras model
    """
    # First, define the vision modules
    # img input
    input_img = Input((*model_image_size, 3))
    # build basemodel
    if basemodel_name == 'resnet50':
        basemodel = ResNet50(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'xception':
        basemodel = Xception(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'inception_v3':
        basemodel = InceptionV3(input_tensor=input_img,
                                weights='imagenet',
                                include_top=False)
    elif basemodel_name == 'inception_resnet_v2':
        basemodel = InceptionResNetV2(input_tensor=input_img,
                                      weights='imagenet',
                                      include_top=False)
    else:
        print('basemodel_name not defined!')
        raise NameError
    # use serveral layers as output
    out_2_35 = basemodel.get_layer(name='mixed2').output  #block1_conv1
    out_5_17 = basemodel.get_layer(name='mixed4').output
    vision_model = Model(input_img, [out_2_35, out_5_17], name='vision_model')
    # get output for a and b
    input_a = Input((*model_image_size, 3), name='input_a')
    input_b = Input((*model_image_size, 3), name='input_b')
    a_out_2_35, a_out_5_17 = vision_model(input_a)
    b_out_2_35, b_out_5_17 = vision_model(input_b)

    # define abs layers
    #my_abs = Lambda(lambda z: K.abs(z))
    # sub
    #p_low = concatenate([a_out_2_35, b_out_2_35])
    #sub_1 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(Subtract(name='sub2')([a_out_2_35, b_out_2_35]))

    sub_4 = (Subtract(name='sub4')([a_out_5_17, b_out_5_17]))

    x1 = sub_4

    x = conv2d_bn(x1, 10, 1, 1, name='after_conv_2')
    # flatten
    y = Flatten(name='after_flatten')(x)
    # add some dense layers
    y = Dense(128, activation='relu', name='after_dense_1')(y)
    out = Dense(1, activation='sigmoid')(y)
    return Model([input_a, input_b], out)
Exemple #2
0
def inception_v3_mixed_module(x):
    if image_data_format() == 'channels_first':
        channel_axis = 1
    else:
        channel_axis = 3

    branch1x1 = conv2d_bn(x, 64, 1, 1)
    branch5x5 = conv2d_bn(x, 48, 1, 1)
    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)
    branch3x3dbl = conv2d_bn(x, 64, 1, 1)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch_pool = layers.AveragePooling2D((3, 3),
                                          strides=(1, 1),
                                          padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 32, 1, 1)
    return layers.concatenate(
        [branch1x1, branch5x5, branch3x3dbl, branch_pool], axis=channel_axis)
Exemple #3
0
def localize_classify_deep(fine_tune=False):
    model = InceptionV3(include_top=False, input_shape=(299, 299, 3))
    if fine_tune:
        for layer in model.layers:
            layer.trainable = False
    output = model.get_layer(index=-1).output
    # 8x8x1024
    branch1x1 = conv2d_bn(output, 160, 1, 1)

    branch3x3 = conv2d_bn(output, 192, 1, 1)
    branch3x3_1 = conv2d_bn(branch3x3, 192, 1, 3)
    branch3x3_2 = conv2d_bn(branch3x3, 192, 3, 1)
    branch3x3 = merge([branch3x3_1, branch3x3_2],
                      mode='concat',
                      concat_axis=-1)

    branch3x3dbl = conv2d_bn(output, 224, 1, 1)
    branch3x3dbl = conv2d_bn(output, 192, 3, 3)
    branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 192, 1, 3)
    branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 192, 3, 1)
    branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2],
                         mode='concat',
                         concat_axis=-1)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                   border_mode='same')(output)
    branch_pool = conv2d_bn(branch_pool, 96, 1, 1)
    output = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool],
                   mode='concat',
                   concat_axis=-1)

    # 8x8x512
    branch1x1 = conv2d_bn(output, 80, 1, 1)

    branch3x3 = conv2d_bn(output, 96, 1, 1)
    branch3x3_1 = conv2d_bn(branch3x3, 96, 1, 3)
    branch3x3_2 = conv2d_bn(branch3x3, 96, 3, 1)
    branch3x3 = merge([branch3x3_1, branch3x3_2],
                      mode='concat',
                      concat_axis=-1)

    branch3x3dbl = conv2d_bn(output, 112, 1, 1)
    branch3x3dbl = conv2d_bn(output, 96, 3, 3)
    branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 96, 1, 3)
    branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 96, 3, 1)
    branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2],
                         mode='concat',
                         concat_axis=-1)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                   border_mode='same')(output)
    branch_pool = conv2d_bn(branch_pool, 48, 1, 1)
    output = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool],
                   mode='concat',
                   concat_axis=-1)

    localize = Convolution2D(4, 1, 1)(output)
    localize = GlobalAveragePooling2D(name='localize')(localize)
    classify = Convolution2D(8, 1, 1)(output)
    classify = GlobalAveragePooling2D()(classify)
    classify = Activation('softmax', name=OUTPUT_NAME)(classify)

    model = Model(model.input, [localize, classify])
    return model
Exemple #4
0
def localize(fine_tune=False):
    from keras.models import Model
    model = InceptionV3(include_top=False, input_shape=(299, 299, 3))
    if fine_tune:
        for layer in model.layers:
            layer.trainable = False
    output = model.get_layer(index=-1).output
    # 8x8x1024
    branch1x1 = conv2d_bn(output, 160, 1, 1)

    branch3x3 = conv2d_bn(output, 192, 1, 1)
    branch3x3_1 = conv2d_bn(branch3x3, 192, 1, 3)
    branch3x3_2 = conv2d_bn(branch3x3, 192, 3, 1)
    branch3x3 = merge([branch3x3_1, branch3x3_2],
                      mode='concat',
                      concat_axis=-1)

    branch3x3dbl = conv2d_bn(output, 224, 1, 1)
    branch3x3dbl = conv2d_bn(output, 192, 3, 3)
    branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 192, 1, 3)
    branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 192, 3, 1)
    branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2],
                         mode='concat',
                         concat_axis=-1)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                   border_mode='same')(output)
    branch_pool = conv2d_bn(branch_pool, 96, 1, 1)
    output = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool],
                   mode='concat',
                   concat_axis=-1)

    # 8x8x512
    branch1x1 = conv2d_bn(output, 80, 1, 1)

    branch3x3 = conv2d_bn(output, 96, 1, 1)
    branch3x3_1 = conv2d_bn(branch3x3, 96, 1, 3)
    branch3x3_2 = conv2d_bn(branch3x3, 96, 3, 1)
    branch3x3 = merge([branch3x3_1, branch3x3_2],
                      mode='concat',
                      concat_axis=-1)

    branch3x3dbl = conv2d_bn(output, 112, 1, 1)
    branch3x3dbl = conv2d_bn(output, 96, 3, 3)
    branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 96, 1, 3)
    branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 96, 3, 1)
    branch3x3dbl = merge([branch3x3dbl_1, branch3x3dbl_2],
                         mode='concat',
                         concat_axis=-1)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                   border_mode='same')(output)
    branch_pool = conv2d_bn(branch_pool, 48, 1, 1)
    output = merge([branch1x1, branch3x3, branch3x3dbl, branch_pool],
                   mode='concat',
                   concat_axis=-1)

    localize = Convolution2D(4, 1, 1)(output)
    localize = GlobalAveragePooling2D(name='localize')(localize)

    model = Model(model.input, localize)
    return model
def InceptionV3_deform_model(nb_classes):
    if K.image_data_format() == 'channels_first':
        channel_axis = 1
    else:
        channel_axis = 3

    img_input = InceptionV3().input
    x = conv2d_bn(img_input, 32, 3, 3, strides=(2, 2), padding='valid')
    x = ConvOffset2D(32, name='conv1_offset')(x)
    x = conv2d_bn(x, 32, 3, 3, padding='valid')
    x = ConvOffset2D(32, name='conv2_offset')(x)
    x = conv2d_bn(x, 64, 3, 3)
    x = MaxPooling2D((3, 3), strides=(2, 2))(x)

    x = conv2d_bn(x, 80, 1, 1, padding='valid')
    x = ConvOffset2D(80, name='conv3_offset')(x)
    x = conv2d_bn(x, 192, 3, 3, padding='valid')
    x = MaxPooling2D((3, 3), strides=(2, 2))(x)

    # mixed 0, 1, 2: 35 x 35 x 256
    branch1x1 = conv2d_bn(x, 64, 1, 1)

    branch5x5 = conv2d_bn(x, 48, 1, 1)
    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)

    branch3x3dbl = conv2d_bn(x, 64, 1, 1)
    branch3x3dbl = ConvOffset2D(64, name='conv4_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch3x3dbl = ConvOffset2D(96, name='conv5_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 32, 1, 1)
    x = concatenate([branch1x1, branch5x5, branch3x3dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed0')

    # mixed 1: 35 x 35 x 256
    branch1x1 = conv2d_bn(x, 64, 1, 1)

    branch5x5 = conv2d_bn(x, 48, 1, 1)
    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)

    branch3x3dbl = conv2d_bn(x, 64, 1, 1)
    branch3x3dbl = ConvOffset2D(64, name='conv6_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch3x3dbl = ConvOffset2D(96, name='conv7_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 64, 1, 1)
    x = concatenate([branch1x1, branch5x5, branch3x3dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed1')

    # mixed 2: 35 x 35 x 256
    branch1x1 = conv2d_bn(x, 64, 1, 1)

    branch5x5 = conv2d_bn(x, 48, 1, 1)
    branch5x5 = conv2d_bn(branch5x5, 64, 5, 5)

    branch3x3dbl = conv2d_bn(x, 64, 1, 1)
    branch3x3dbl = ConvOffset2D(64, name='conv8_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch3x3dbl = ConvOffset2D(96, name='conv9_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 64, 1, 1)
    x = concatenate([branch1x1, branch5x5, branch3x3dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed2')

    # mixed 3: 17 x 17 x 768
    x = ConvOffset2D(288, name='conv10_offset')(x)
    branch3x3 = conv2d_bn(x, 384, 3, 3, strides=(2, 2), padding='valid')

    branch3x3dbl = conv2d_bn(x, 64, 1, 1)
    branch3x3dbl = ConvOffset2D(64, name='conv11_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl, 96, 3, 3)
    branch3x3dbl = ConvOffset2D(96, name='conv12_offset')(branch3x3dbl)
    branch3x3dbl = conv2d_bn(branch3x3dbl,
                             96,
                             3,
                             3,
                             strides=(2, 2),
                             padding='valid')

    branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)
    x = concatenate([branch3x3, branch3x3dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed3')

    # mixed 4: 17 x 17 x 768
    branch1x1 = conv2d_bn(x, 192, 1, 1)

    branch7x7 = conv2d_bn(x, 128, 1, 1)
    branch7x7 = conv2d_bn(branch7x7, 128, 1, 7)
    branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)

    branch7x7dbl = conv2d_bn(x, 128, 1, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 1, 7)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 128, 7, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
    x = concatenate([branch1x1, branch7x7, branch7x7dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed4')

    # mixed 5, 6: 17 x 17 x 768
    for i in range(2):
        branch1x1 = conv2d_bn(x, 192, 1, 1)

        branch7x7 = conv2d_bn(x, 160, 1, 1)
        branch7x7 = conv2d_bn(branch7x7, 160, 1, 7)
        branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)

        branch7x7dbl = conv2d_bn(x, 160, 1, 1)
        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)
        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 1, 7)
        branch7x7dbl = conv2d_bn(branch7x7dbl, 160, 7, 1)
        branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)

        branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                       padding='same')(x)
        branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
        x = concatenate([branch1x1, branch7x7, branch7x7dbl, branch_pool],
                        axis=channel_axis,
                        name='mixed' + str(5 + i))

    # mixed 7: 17 x 17 x 768
    branch1x1 = conv2d_bn(x, 192, 1, 1)

    branch7x7 = conv2d_bn(x, 192, 1, 1)
    branch7x7 = conv2d_bn(branch7x7, 192, 1, 7)
    branch7x7 = conv2d_bn(branch7x7, 192, 7, 1)

    branch7x7dbl = conv2d_bn(x, 192, 1, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 7, 1)
    branch7x7dbl = conv2d_bn(branch7x7dbl, 192, 1, 7)

    branch_pool = AveragePooling2D((3, 3), strides=(1, 1), padding='same')(x)
    branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
    x = concatenate([branch1x1, branch7x7, branch7x7dbl, branch_pool],
                    axis=channel_axis,
                    name='mixed7')

    # mixed 8: 8 x 8 x 1280
    branch3x3 = conv2d_bn(x, 192, 1, 1)
    branch3x3 = ConvOffset2D(192, name='conv13_offset')(branch3x3)
    branch3x3 = conv2d_bn(branch3x3,
                          320,
                          3,
                          3,
                          strides=(2, 2),
                          padding='valid')

    branch7x7x3 = conv2d_bn(x, 192, 1, 1)
    branch7x7x3 = conv2d_bn(branch7x7x3, 192, 1, 7)
    branch7x7x3 = conv2d_bn(branch7x7x3, 192, 7, 1)
    branch7x7x3 = ConvOffset2D(192, name='conv14_offset')(branch7x7x3)
    branch7x7x3 = conv2d_bn(branch7x7x3,
                            192,
                            3,
                            3,
                            strides=(2, 2),
                            padding='valid')

    branch_pool = MaxPooling2D((3, 3), strides=(2, 2))(x)
    x = concatenate([branch3x3, branch7x7x3, branch_pool],
                    axis=channel_axis,
                    name='mixed8')

    # mixed 9: 8 x 8 x 2048
    for i in range(2):
        branch1x1 = conv2d_bn(x, 320, 1, 1)

        branch3x3 = conv2d_bn(x, 384, 1, 1)
        branch3x3_1 = conv2d_bn(branch3x3, 384, 1, 3)
        branch3x3_2 = conv2d_bn(branch3x3, 384, 3, 1)
        branch3x3 = concatenate([branch3x3_1, branch3x3_2],
                                axis=channel_axis,
                                name='mixed9_' + str(i))

        branch3x3dbl = conv2d_bn(x, 448, 1, 1)
        branch3x3dbl = ConvOffset2D(448, name='conv15_%d_offset' %
                                    (i))(branch3x3dbl)
        branch3x3dbl = conv2d_bn(branch3x3dbl, 384, 3, 3)
        branch3x3dbl_1 = conv2d_bn(branch3x3dbl, 384, 1, 3)
        branch3x3dbl_2 = conv2d_bn(branch3x3dbl, 384, 3, 1)
        branch3x3dbl = concatenate([branch3x3dbl_1, branch3x3dbl_2],
                                   axis=channel_axis)

        branch_pool = AveragePooling2D((3, 3), strides=(1, 1),
                                       padding='same')(x)
        branch_pool = conv2d_bn(branch_pool, 192, 1, 1)
        x = concatenate([branch1x1, branch3x3, branch3x3dbl, branch_pool],
                        axis=channel_axis,
                        name='mixed' + str(9 + i))

    # Classification block
    x = GlobalAveragePooling2D(name='avg_pool')(x)
    x = Dense(nb_classes, activation='softmax', name='predictions')(x)

    # Ensure that the model takes into account
    # any potential predecessors of `input_tensor`.

    inputs = img_input
    # Create model.
    model = Model(inputs, x, name='inception_v3_deform')
    return model
def model_v3(basemodel_name, model_image_size=(360, 480)):
    """ use conv output 7 column
    :param basemodel_name: string, one of 'resnet50', 'xception', 'inception_v3' or 'inception_resnet_v2'
    :param model_image_size: original size is 540(height)*720(width)
    :return: keras model
    """
    # First, define the vision modules
    # img input
    input_img = Input((*model_image_size, 3))
    # build basemodel
    if basemodel_name == 'resnet50':
        basemodel = ResNet50(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'xception':
        basemodel = Xception(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'inception_v3':
        basemodel = InceptionV3(input_tensor=input_img,
                                weights='imagenet',
                                include_top=False)
    elif basemodel_name == 'inception_resnet_v2':
        basemodel = InceptionResNetV2(input_tensor=input_img,
                                      weights='imagenet',
                                      include_top=False)
    else:
        print('basemodel_name not defined!')
        raise NameError
    # get serveral output layers
    out_0_35 = basemodel.get_layer(name='mixed0').output
    out_1_35 = basemodel.get_layer(name='mixed1').output
    out_2_35 = basemodel.get_layer(name='mixed2').output
    out_3_17 = basemodel.get_layer(name='mixed3').output
    out_4_17 = basemodel.get_layer(name='mixed4').output
    vision_model = Model(input_img,
                         [out_0_35, out_1_35, out_2_35, out_3_17, out_4_17],
                         name='vision_model')

    # Then define the tell-img-apart model
    input_a = Input((*model_image_size, 3), name='input_a')
    input_b = Input((*model_image_size, 3), name='input_b')
    # The vision model will be shared, weights and all
    a_out_0_35, a_out_1_35, a_out_2_35, a_out_3_17, a_out_4_17 = vision_model(
        input_a)
    b_out_0_35, b_out_1_35, b_out_2_35, b_out_3_17, b_out_4_17 = vision_model(
        input_b)
    sub_0_35 = Subtract(name='sub0')([a_out_0_35, b_out_0_35])
    sub_1_35 = Subtract(name='sub1')([a_out_1_35, b_out_1_35])
    sub_2_35 = Subtract(name='sub2')([a_out_2_35, b_out_2_35])
    sub_3_17 = Subtract(name='sub3')([a_out_3_17, b_out_3_17])
    sub_4_17 = Subtract(name='sub4')([a_out_4_17, b_out_4_17])
    l0 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(sub_0_35)
    l1 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(sub_1_35)
    l2 = MaxPooling2D((3, 3), strides=(2, 2), padding='valid')(sub_2_35)
    l_35 = MaxPooling2D((3, 3), strides=(2, 2),
                        padding='valid')(concatenate([a_out_2_35, b_out_2_35]))
    l_17 = concatenate([a_out_4_17, b_out_4_17])
    x1 = concatenate([l0, l1, l2, sub_3_17, sub_4_17])
    x2 = concatenate([l_35, l_17])
    # add some conv layers
    x1 = conv2d_bn(x1, 128, 1, 1, name='after_conv_x1')
    x2 = conv2d_bn(x2, 128, 1, 1, name='after_conv_x2')
    x = concatenate([x1, x2])
    x = conv2d_bn(x, 10, 1, 1, name='after_conv_2')
    # flatten
    y = Flatten(name='after_flatten')(x)
    # add some dense layers
    y = Dense(128, activation='relu', name='after_dense_1')(y)
    out = Dense(1, activation='sigmoid')(y)
    return Model([input_a, input_b], out)
def model_v4(basemodel_name, model_image_size=(360, 480)):
    """
    :param basemodel_name: string, one of 'resnet50', 'xception', 'inception_v3' or 'inception_resnet_v2'
    :param model_image_size: original size is 540(height)*720(width)
    :return: keras model
    """
    # First, define the vision modules
    # img input
    input_img = Input((*model_image_size, 3))
    # build basemodel
    if basemodel_name == 'resnet50':
        basemodel = ResNet50(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'xception':
        basemodel = Xception(input_tensor=input_img,
                             weights='imagenet',
                             include_top=False)
    elif basemodel_name == 'inception_v3':
        basemodel = InceptionV3(input_tensor=input_img,
                                weights='imagenet',
                                include_top=False)
    elif basemodel_name == 'inception_resnet_v2':
        basemodel = InceptionResNetV2(input_tensor=input_img,
                                      weights='imagenet',
                                      include_top=False)
    else:
        print('basemodel_name not defined!')
        raise NameError
    # use serveral layers as output
    out_0_35 = basemodel.get_layer(name='mixed0').output
    out_1_35 = basemodel.get_layer(name='mixed1').output
    out_2_35 = basemodel.get_layer(name='mixed2').output
    out_3_17 = basemodel.get_layer(name='mixed3').output
    out_4_17 = basemodel.get_layer(name='mixed4').output
    out_5_17 = basemodel.get_layer(name='mixed5').output
    vision_model = Model(
        input_img,
        [out_0_35, out_1_35, out_2_35, out_3_17, out_4_17, out_5_17],
        name='vision_model')
    # get output for a and b
    input_a = Input((*model_image_size, 3), name='input_a')
    input_b = Input((*model_image_size, 3), name='input_b')
    a_out_0_35, a_out_1_35, a_out_2_35, a_out_3_17, a_out_4_17, a_out_5_17 = vision_model(
        input_a)
    b_out_0_35, b_out_1_35, b_out_2_35, b_out_3_17, b_out_4_17, b_out_5_17 = vision_model(
        input_b)
    # Then, define the tell-img-apart model
    # define abs layers
    my_abs = Lambda(lambda z: K.abs(z))
    # sub
    sub_0_35 = my_abs(Subtract(name='sub0')([a_out_0_35, b_out_0_35]))
    sub_1_35 = my_abs(Subtract(name='sub1')([a_out_1_35, b_out_1_35]))
    sub_2_35 = my_abs(Subtract(name='sub2')([a_out_2_35, b_out_2_35]))
    sub_3_17 = my_abs(Subtract(name='sub3')([a_out_3_17, b_out_3_17]))
    sub_4_17 = my_abs(Subtract(name='sub4')([a_out_4_17, b_out_4_17]))
    sub_5_17 = my_abs(Subtract(name='sub5')([a_out_5_17, b_out_5_17]))
    # max poool
    sub_35 = MaxPooling2D(
        (3, 3), strides=(2, 2),
        padding='valid')(concatenate([sub_0_35, sub_1_35, sub_2_35]))
    x_sub = concatenate([sub_35, sub_3_17, sub_4_17, sub_5_17])
    # original
    ori_35 = MaxPooling2D(
        (3, 3), strides=(2, 2),
        padding='valid')(concatenate([a_out_2_35, b_out_2_35]))
    x_ori = concatenate([ori_35, a_out_5_17, b_out_5_17])
    # add some conv layers
    x_sub = conv2d_bn(x_sub, 128, 1, 1, name='after_conv_sub')
    x_ori = conv2d_bn(x_ori, 128, 1, 1, name='after_conv_ori')
    x = concatenate([x_sub, x_ori])
    x = conv2d_bn(x, 10, 1, 1, name='after_conv_1')
    # flatten
    y = Flatten(name='after_flatten')(x)
    # add some dense layers
    y = Dense(128, activation='relu', name='after_dense_1')(y)
    out = Dense(1, activation='sigmoid', name='output_dense')(y)
    return Model([input_a, input_b], out)