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)
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)
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
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)