def make_last_layers(x, num_filters, out_filters): """6 Conv2D_BN_Leaky layers followed by a Conv2D_linear layer""" x = compose(DarknetConv2D_BN_Leaky(num_filters, (1, 1)), DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D_BN_Leaky(num_filters, (1, 1)), DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D_BN_Leaky(num_filters, (1, 1)))(x) y = compose(DarknetConv2D_BN_Leaky(num_filters * 2, (3, 3)), DarknetConv2D(out_filters, (1, 1)))(x) return x, y
def yolo_body_2(inputs, num_anchors, num_classes, pruning=None, n_blocks=23): global init_string init_string = 'glorot_uniform' darknet = Model(inputs, darknet_body_2(inputs, n_blocks, True)) darknet_orig = Model(inputs, darknet_body_2(inputs, n_blocks, False)) # no second part if n_blocks <= 23: return Model(inputs, [darknet, darknet_orig]) # non-orig x, y1 = make_last_layers(darknet.output, 512, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, out2]) x, y2 = make_last_layers(x, 256, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, out1]) x, y3 = make_last_layers(x, 128, num_anchors * (num_classes + 5)) # orig x_orig, y1_orig = make_last_layers(darknet_orig.output, 512, num_anchors * (num_classes + 5)) x_orig = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x_orig) x_orig = Concatenate()([x_orig, out2_orig]) x_orig, y2_orig = make_last_layers(x_orig, 256, num_anchors * (num_classes + 5)) x_orig = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x_orig) x_orig = Concatenate()([x_orig, out1_orig]) x_orig, y3_orig = make_last_layers(x_orig, 128, num_anchors * (num_classes + 5)) init_string = 'zeros' return Model(inputs, [y1, y2, y3, y1_orig, y2_orig, y3_orig])
def mixed_resblock_body(x, num_filters, num_blocks, n_inverted=0): n_multipl = 1 # unit of changing blocks at once # there are both inverted- and normal residual blocks if n_multipl * n_inverted < num_blocks: x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = DarknetConv2D_BN_Leaky(num_filters, (3, 3), strides=(2, 2))(x) # only inverted residual blocks else: x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = MobilenetSeparableConv2D_BN_ReLU(num_filters // 2, (3, 3), strides=(2, 2))(x) x = Conv2D(num_filters // 2, (1, 1))(x) # TODO nem lesz jó # add normal residual blocks for i in range(0, num_blocks - n_multipl * n_inverted): y = compose(DarknetConv2D_BN_Leaky(num_filters // 2, (1, 1)), DarknetConv2D_BN_Leaky(num_filters, (3, 3)))(x) x = Add()([x, y]) global i_name i_name += 1 # TODO: what to do with this layer? if n_inverted > 0: x = Conv2D(num_filters // 2, (1, 1), name='conv2d_adapter_' + str(i_name))(x) # add inverted residual blocks # todo freeze all except last iteration: only when (n_multipl * n_inverted == num_blocks) for i in range(0, n_multipl * n_inverted): y = compose( MobilenetConv2D_BN_ReLU(num_filters // 2, (1, 1)), MobilenetSeparableConv2D_BN_ReLU(num_filters // 2 * 6, (3, 3), strides=(1, 1)), MobilenetConv2D_BN_Linear(num_filters // 2, (1, 1)))(x) x = Add()([x, y]) if n_inverted > 0: x = Conv2D(num_filters, (1, 1), name='conv2d_adapter2_' + str(i_name))(x) return x
def MobilenetSeparableConv2D_BN_ReLU(*args, **kwargs): """Darknet Convolution2D followed by BatchNormalization and LeakyReLU.""" no_bias_kwargs = {'use_bias': False} no_bias_kwargs.update(kwargs) global i_name i_name += 1 return compose( MobilenetSeparableConv2D(*args, **no_bias_kwargs), BatchNormalization(name='batch_normalization_extra_' + str(i_name)), # TODO delete name ReLU(max_value=6))
def yolo_body(inputs, num_anchors, num_classes, pruning=None, mod_mask=(0, 0, 0, 0, 0)): """Create YOLO_V3 model CNN body in Keras.""" darknet = Model(inputs, darknet_body(inputs, pruning, mod_mask)) x, y1 = make_last_layers(darknet.output, 512, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(256, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, out2]) x, y2 = make_last_layers(x, 256, num_anchors * (num_classes + 5)) x = compose(DarknetConv2D_BN_Leaky(128, (1, 1)), UpSampling2D(2))(x) x = Concatenate()([x, out1]) x, y3 = make_last_layers(x, 128, num_anchors * (num_classes + 5)) # model_1st_part = Model(input=inputs, output=cutting_layer_out) # model_2nd_part = Model(input=model_1st_part.output, output=cutting_layer_in) return Model(inputs, [y1, y2, y3])
def resblock_body(x, num_filters, num_blocks): """A series of resblocks starting with a downsampling Convolution2D""" if num_blocks == 0: return x # Darknet uses left and top padding instead of 'same' mode x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = DarknetConv2D_BN_Leaky(num_filters, (3, 3), strides=(2, 2))(x) for i in range(0, num_blocks): y = compose(DarknetConv2D_BN_Leaky(num_filters // 2, (1, 1)), DarknetConv2D_BN_Leaky(num_filters, (3, 3)))(x) x = Add()([x, y]) return x
def inverted_resblock_body(x, num_filters, num_blocks): if num_blocks == 0: return x x = ZeroPadding2D(((1, 0), (1, 0)))(x) x = MobilenetSeparableConv2D_BN_ReLU(num_filters // 2, (3, 3), strides=(2, 2))(x) for i in range(0, num_blocks): y = compose( MobilenetConv2D_BN_ReLU(num_filters // 2, (1, 1)), MobilenetSeparableConv2D_BN_ReLU(num_filters // 2 * 6, (3, 3), strides=(1, 1)), MobilenetConv2D_BN_Linear(num_filters // 2, (1, 1)))(x) x = Add()([x, y]) return x
def MobilenetConv2D_BN_Linear(*args, **kwargs): """Darknet Convolution2D followed by BatchNormalization and LeakyReLU.""" no_bias_kwargs = {'use_bias': False} no_bias_kwargs.update(kwargs) return compose(DarknetConv2D(*args, **no_bias_kwargs), BatchNormalization())