コード例 #1
0
def DarknetDepthwiseConv2D(*args, **kwargs):
    """Wrapper to set Darknet parameters for YoloDepthwiseConv2D."""
    #darknet_conv_kwargs = {'kernel_regularizer': l2(5e-4)}
    #darknet_conv_kwargs['padding'] = 'valid' if kwargs.get('strides')==(2,2) else 'same'
    darknet_conv_kwargs = {'padding': 'valid' if kwargs.get('strides')==(2,2) else 'same'}
    darknet_conv_kwargs.update(kwargs)
    return YoloDepthwiseConv2D(*args, **darknet_conv_kwargs)
コード例 #2
0
def cheap_operations(x, output_filters, kernel_size, strides=(1,1), padding='same', act=True, use_bias=False, name=None):
    x = YoloDepthwiseConv2D(kernel_size=kernel_size,
                        strides=strides,
                        padding=padding,
                        use_bias=use_bias,
                        name=name+'_0')(x)
    x = CustomBatchNormalization(name=name+'_1')(x)
    x = ReLU(name=name+'_relu')(x) if act else x
    return x
コード例 #3
0
def GhostBottleneck(input_x, mid_chs, out_chs, dw_kernel_size=3, stride=(1,1), se_ratio=0., name=None):
    '''ghostnet bottleneck w/optional se'''
    has_se = se_ratio is not None and se_ratio > 0.

    #1st ghost bottleneck
    x = GhostModule(input_x, mid_chs, act=True, name=name+'_ghost1')

    #depth_with convolution
    if stride[0] > 1:
        x = YoloDepthwiseConv2D(kernel_size=dw_kernel_size,
                            strides=stride,
                            padding='same',
                            use_bias=False,
                            name=name+'_conv_dw')(x)
        x = CustomBatchNormalization(name=name+'_bn_dw')(x)

    #Squeeze_and_excitation
    if has_se:
        x = SqueezeExcite(x, se_ratio=se_ratio, name=name+'_se')

    #2nd ghost bottleneck
    x = GhostModule(x, out_chs, act=False, name=name+'_ghost2')

    #short cut
    if (input_x.shape[-1] == out_chs and stride[0] == 1):
        sc = input_x
    else:
        name1 = name + '_shortcut'
        sc = YoloDepthwiseConv2D(kernel_size=dw_kernel_size,
                             strides=stride,
                             padding='same',
                             use_bias=False,
                             name=name1+'_0')(input_x)
        sc = CustomBatchNormalization(name=name1+'_1')(sc)
        sc = YoloConv2D(filters=out_chs,
                    kernel_size=1,
                    strides=(1,1),
                    padding='valid',
                    use_bias=False,
                    name=name1+'_2')(sc)
        sc = CustomBatchNormalization(name=name1+'_3')(sc)

    x = Add(name=name+'_add')([x, sc])
    return x
コード例 #4
0
def _inverted_res_block(inputs, expansion, stride, alpha, filters, block_id):
    channel_axis = 1 if K.image_data_format() == 'channels_first' else -1

    in_channels = K.int_shape(inputs)[channel_axis]
    pointwise_conv_filters = int(filters * alpha)
    pointwise_filters = _make_divisible(pointwise_conv_filters, 8)
    x = inputs
    prefix = 'block_{}_'.format(block_id)

    if block_id:
        # Expand
        x = YoloConv2D(expansion * in_channels,
                       kernel_size=1,
                       padding='same',
                       use_bias=False,
                       activation=None,
                       name=prefix + 'expand')(x)
        x = CustomBatchNormalization(axis=channel_axis,
                                     epsilon=1e-3,
                                     momentum=0.999,
                                     name=prefix + 'expand_BN')(x)
        x = ReLU(6., name=prefix + 'expand_relu')(x)
    else:
        prefix = 'expanded_conv_'

    # Depthwise
    if stride == 2:
        x = ZeroPadding2D(padding=correct_pad(K, x, 3), name=prefix + 'pad')(x)
    x = YoloDepthwiseConv2D(kernel_size=3,
                            strides=stride,
                            activation=None,
                            use_bias=False,
                            padding='same' if stride == 1 else 'valid',
                            name=prefix + 'depthwise')(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'depthwise_BN')(x)

    x = ReLU(6., name=prefix + 'depthwise_relu')(x)

    # Project
    x = YoloConv2D(pointwise_filters,
                   kernel_size=1,
                   padding='same',
                   use_bias=False,
                   activation=None,
                   name=prefix + 'project')(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'project_BN')(x)

    if in_channels == pointwise_filters and stride == 1:
        return Add(name=prefix + 'add')([inputs, x])
    return x
コード例 #5
0
def Depthwise_Conv2D_BN_Leaky(kernel_size=(3, 3), block_id_str=None):
    """Depthwise Convolution2D."""
    if not block_id_str:
        block_id_str = str(K.get_uid())
    return compose(
        YoloDepthwiseConv2D(kernel_size,
                            padding='same',
                            name='conv_dw_' + block_id_str),
        CustomBatchNormalization(name='conv_dw_%s_bn' % block_id_str),
        LeakyReLU(alpha=0.1, name='conv_dw_%s_leaky_relu' % block_id_str))
コード例 #6
0
def Depthwise_Separable_Conv2D_BN_Leaky(filters, kernel_size=(3, 3), block_id_str=None):
    """Depthwise Separable Convolution2D."""
    if not block_id_str:
        block_id_str = str(K.get_uid())
    return compose(
        YoloDepthwiseConv2D(kernel_size, padding='same', name='conv_dw_' + block_id_str),
        CustomBatchNormalization(name='conv_dw_%s_bn' % block_id_str),
        LeakyReLU(alpha=0.1, name='conv_dw_%s_leaky_relu' % block_id_str),
        YoloConv2D(filters, (1,1), padding='same', use_bias=False, strides=(1, 1), name='conv_pw_%s' % block_id_str),
        CustomBatchNormalization(name='conv_pw_%s_bn' % block_id_str),
        LeakyReLU(alpha=0.1, name='conv_pw_%s_leaky_relu' % block_id_str))
コード例 #7
0
def _inverted_res_block(x, expansion, filters, kernel_size, stride, se_ratio,
                        activation, block_id):
    channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
    shortcut = x
    prefix = 'expanded_conv/'
    infilters = K.int_shape(x)[channel_axis]
    if block_id:
        # Expand
        prefix = 'expanded_conv_{}/'.format(block_id)
        x = YoloConv2D(_depth(infilters * expansion),
                       kernel_size=1,
                       padding='same',
                       use_bias=False,
                       name=prefix + 'expand')(x)
        x = CustomBatchNormalization(axis=channel_axis,
                                     epsilon=1e-3,
                                     momentum=0.999,
                                     name=prefix + 'expand/BatchNorm')(x)
        x = Activation(activation)(x)

    if stride == 2:
        x = ZeroPadding2D(padding=correct_pad(K, x, kernel_size),
                          name=prefix + 'depthwise/pad')(x)
    x = YoloDepthwiseConv2D(kernel_size,
                            strides=stride,
                            padding='same' if stride == 1 else 'valid',
                            use_bias=False,
                            name=prefix + 'depthwise/Conv')(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'depthwise/BatchNorm')(x)
    x = Activation(activation)(x)

    if se_ratio:
        x = _se_block(x, _depth(infilters * expansion), se_ratio, prefix)

    x = YoloConv2D(filters,
                   kernel_size=1,
                   padding='same',
                   use_bias=False,
                   name=prefix + 'project')(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'project/BatchNorm')(x)

    if stride == 1 and infilters == filters:
        x = Add(name=prefix + 'Add')([shortcut, x])
    return x
コード例 #8
0
def _ep_block(inputs, filters, stride, expansion, block_id):
    #in_channels = backend.int_shape(inputs)[-1]
    in_channels = inputs.shape.as_list()[-1]

    pointwise_conv_filters = int(filters)
    x = inputs
    prefix = 'ep_block_{}_'.format(block_id)

    # Expand
    x = YoloConv2D(int(expansion * in_channels),
                   kernel_size=1,
                   padding='same',
                   use_bias=False,
                   activation=None,
                   name=prefix + 'expand')(x)
    x = CustomBatchNormalization(epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'expand_BN')(x)
    x = ReLU(6., name=prefix + 'expand_relu')(x)

    # Depthwise
    if stride == 2:
        x = ZeroPadding2D(padding=correct_pad(K, x, 3), name=prefix + 'pad')(x)

    x = YoloDepthwiseConv2D(kernel_size=3,
                            strides=stride,
                            activation=None,
                            use_bias=False,
                            padding='same' if stride == 1 else 'valid',
                            name=prefix + 'depthwise')(x)
    x = CustomBatchNormalization(epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'depthwise_BN')(x)
    x = ReLU(6., name=prefix + 'depthwise_relu')(x)

    # Project
    x = YoloConv2D(pointwise_conv_filters,
                   kernel_size=1,
                   padding='same',
                   use_bias=False,
                   activation=None,
                   name=prefix + 'project')(x)
    x = CustomBatchNormalization(epsilon=1e-3,
                                 momentum=0.999,
                                 name=prefix + 'project_BN')(x)

    if in_channels == pointwise_conv_filters and stride == 1:
        return Add(name=prefix + 'add')([inputs, x])
    return x
コード例 #9
0
def _shuffle_unit(inputs,
                  in_channels,
                  out_channels,
                  groups,
                  bottleneck_ratio,
                  strides=2,
                  stage=1,
                  block=1):
    """
    creates a shuffleunit
    Parameters
    ----------
    inputs:
        Input tensor of with `channels_last` data format
    in_channels:
        number of input channels
    out_channels:
        number of output channels
    strides:
        An integer or tuple/list of 2 integers,
        specifying the strides of the convolution along the width and height.
    groups: int(1)
        number of groups per channel
    bottleneck_ratio: float
        bottleneck ratio implies the ratio of bottleneck channels to output channels.
        For example, bottleneck ratio = 1 : 4 means the output feature map is 4 times
        the width of the bottleneck feature map.
    stage: int(1)
        stage number
    block: int(1)
        block number
    Returns
    -------
    """
    if K.image_data_format() == 'channels_last':
        bn_axis = -1
    else:
        bn_axis = 1

    prefix = 'stage%d/block%d' % (stage, block)

    #if strides >= 2:
    #out_channels -= in_channels

    # default: 1/4 of the output channel of a ShuffleNet Unit
    bottleneck_channels = int(out_channels * bottleneck_ratio)
    groups = (1 if stage == 2 and block == 1 else groups)

    x = _group_conv(inputs,
                    in_channels,
                    out_channels=bottleneck_channels,
                    groups=(1 if stage == 2 and block == 1 else groups),
                    name='%s/1x1_gconv_1' % prefix)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='%s/bn_gconv_1' % prefix)(x)
    x = Activation('relu', name='%s/relu_gconv_1' % prefix)(x)

    x = Lambda(channel_shuffle,
               arguments={'groups': groups},
               name='%s/channel_shuffle' % prefix)(x)
    x = YoloDepthwiseConv2D(kernel_size=(3, 3),
                            padding="same",
                            use_bias=False,
                            strides=strides,
                            name='%s/1x1_dwconv_1' % prefix)(x)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='%s/bn_dwconv_1' % prefix)(x)

    x = _group_conv(
        x,
        bottleneck_channels,
        out_channels=out_channels if strides == 1 else out_channels -
        in_channels,
        groups=groups,
        name='%s/1x1_gconv_2' % prefix)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='%s/bn_gconv_2' % prefix)(x)

    if strides < 2:
        ret = Add(name='%s/add' % prefix)([x, inputs])
    else:
        avg = AveragePooling2D(pool_size=3,
                               strides=2,
                               padding='same',
                               name='%s/avg_pool' % prefix)(inputs)
        ret = Concatenate(bn_axis, name='%s/concat' % prefix)([x, avg])

    ret = Activation('relu', name='%s/relu_out' % prefix)(ret)

    return ret
コード例 #10
0
def _depthwise_conv_block(inputs,
                          pointwise_conv_filters,
                          alpha,
                          depth_multiplier=1,
                          strides=(1, 1),
                          block_id=1):
    """Adds a depthwise convolution block.

    A depthwise convolution block consists of a depthwise conv,
    batch normalization, relu6, pointwise convolution,
    batch normalization and relu6 activation.

    # Arguments
        inputs: Input tensor of shape `(rows, cols, channels)`
            (with `channels_last` data format) or
            (channels, rows, cols) (with `channels_first` data format).
        pointwise_conv_filters: Integer, the dimensionality of the output space
            (i.e. the number of output filters in the pointwise convolution).
        alpha: controls the width of the network.
            - If `alpha` < 1.0, proportionally decreases the number
                of filters in each layer.
            - If `alpha` > 1.0, proportionally increases the number
                of filters in each layer.
            - If `alpha` = 1, default number of filters from the paper
                 are used at each layer.
        depth_multiplier: The number of depthwise convolution output channels
            for each input channel.
            The total number of depthwise convolution output
            channels will be equal to `filters_in * depth_multiplier`.
        strides: An integer or tuple/list of 2 integers,
            specifying the strides of the convolution
            along the width and height.
            Can be a single integer to specify the same value for
            all spatial dimensions.
            Specifying any stride value != 1 is incompatible with specifying
            any `dilation_rate` value != 1.
        block_id: Integer, a unique identification designating
            the block number.

    # Input shape
        4D tensor with shape:
        `(batch, channels, rows, cols)` if data_format='channels_first'
        or 4D tensor with shape:
        `(batch, rows, cols, channels)` if data_format='channels_last'.

    # Output shape
        4D tensor with shape:
        `(batch, filters, new_rows, new_cols)`
        if data_format='channels_first'
        or 4D tensor with shape:
        `(batch, new_rows, new_cols, filters)`
        if data_format='channels_last'.
        `rows` and `cols` values might have changed due to stride.

    # Returns
        Output tensor of block.
    """
    channel_axis = 1 if K.image_data_format() == 'channels_first' else -1
    pointwise_conv_filters = int(pointwise_conv_filters * alpha)

    if strides == (1, 1):
        x = inputs
    else:
        x = ZeroPadding2D(((0, 1), (0, 1)),
                          name='conv_pad_%d' % block_id)(inputs)
    x = YoloDepthwiseConv2D((3, 3),
                            padding='same' if strides == (1, 1) else 'valid',
                            depth_multiplier=depth_multiplier,
                            strides=strides,
                            use_bias=False,
                            name='conv_dw_%d' % block_id)(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 name='conv_dw_%d_bn' % block_id)(x)
    x = ReLU(6., name='conv_dw_%d_relu' % block_id)(x)

    x = YoloConv2D(pointwise_conv_filters, (1, 1),
                   padding='same',
                   use_bias=False,
                   strides=(1, 1),
                   name='conv_pw_%d' % block_id)(x)
    x = CustomBatchNormalization(axis=channel_axis,
                                 name='conv_pw_%d_bn' % block_id)(x)
    return ReLU(6., name='conv_pw_%d_relu' % block_id)(x)
コード例 #11
0
def block(inputs,
          activation_fn=swish,
          drop_rate=0.,
          name='',
          filters_in=32,
          filters_out=16,
          kernel_size=3,
          strides=1,
          expand_ratio=1,
          se_ratio=0.,
          id_skip=True):
    """A mobile inverted residual block.
    # Arguments
        inputs: input tensor.
        activation_fn: activation function.
        drop_rate: float between 0 and 1, fraction of the input units to drop.
        name: string, block label.
        filters_in: integer, the number of input filters.
        filters_out: integer, the number of output filters.
        kernel_size: integer, the dimension of the convolution window.
        strides: integer, the stride of the convolution.
        expand_ratio: integer, scaling coefficient for the input filters.
        se_ratio: float between 0 and 1, fraction to squeeze the input filters.
        id_skip: boolean.
    # Returns
        output tensor for the block.
    """
    bn_axis = 3 if K.image_data_format() == 'channels_last' else 1

    # Expansion phase
    filters = filters_in * expand_ratio
    if expand_ratio != 1:
        x = YoloConv2D(filters,
                       1,
                       padding='same',
                       use_bias=False,
                       kernel_initializer=CONV_KERNEL_INITIALIZER,
                       name=name + 'expand_conv')(inputs)
        x = CustomBatchNormalization(axis=bn_axis, name=name + 'expand_bn')(x)
        x = Activation(activation_fn, name=name + 'expand_activation')(x)
    else:
        x = inputs

    # Depthwise Convolution
    if strides == 2:
        x = ZeroPadding2D(padding=correct_pad(K, x, kernel_size),
                          name=name + 'dwconv_pad')(x)
        conv_pad = 'valid'
    else:
        conv_pad = 'same'
    x = YoloDepthwiseConv2D(kernel_size,
                            strides=strides,
                            padding=conv_pad,
                            use_bias=False,
                            depthwise_initializer=CONV_KERNEL_INITIALIZER,
                            name=name + 'dwconv')(x)
    x = CustomBatchNormalization(axis=bn_axis, name=name + 'bn')(x)
    x = Activation(activation_fn, name=name + 'activation')(x)

    # Squeeze and Excitation phase
    if 0 < se_ratio <= 1:
        filters_se = max(1, int(filters_in * se_ratio))
        se = GlobalAveragePooling2D(name=name + 'se_squeeze')(x)
        se = Reshape((1, 1, filters), name=name + 'se_reshape')(se)
        se = YoloConv2D(filters_se,
                        1,
                        padding='same',
                        activation=activation_fn,
                        kernel_initializer=CONV_KERNEL_INITIALIZER,
                        name=name + 'se_reduce')(se)
        se = YoloConv2D(filters,
                        1,
                        padding='same',
                        activation='sigmoid',
                        kernel_initializer=CONV_KERNEL_INITIALIZER,
                        name=name + 'se_expand')(se)
        if K.backend() == 'theano':
            # For the Theano backend, we have to explicitly make
            # the excitation weights broadcastable.
            se = Lambda(
                lambda x: K.pattern_broadcast(x, [True, True, True, False]),
                output_shape=lambda input_shape: input_shape,
                name=name + 'se_broadcast')(se)
        x = multiply([x, se], name=name + 'se_excite')

    # Output phase
    x = YoloConv2D(filters_out,
                   1,
                   padding='same',
                   use_bias=False,
                   kernel_initializer=CONV_KERNEL_INITIALIZER,
                   name=name + 'project_conv')(x)
    x = CustomBatchNormalization(axis=bn_axis, name=name + 'project_bn')(x)
    if (id_skip is True and strides == 1 and filters_in == filters_out):
        if drop_rate > 0:
            if tf2.enabled():
                x = Dropout(drop_rate,
                            noise_shape=(None, 1, 1, 1),
                            name=name + 'drop')(x)
            else:
                x = Dropout(
                    drop_rate,
                    #noise_shape=(None, 1, 1, 1),
                    name=name + 'drop')(x)
        x = add([x, inputs], name=name + 'add')

    return x
コード例 #12
0
def shuffle_unit(inputs,
                 out_channels,
                 bottleneck_ratio,
                 strides=2,
                 stage=1,
                 block=1):
    if K.image_data_format() == 'channels_last':
        bn_axis = -1
    else:
        raise ValueError('Only channels last supported')

    prefix = 'stage{}/block{}'.format(stage, block)
    bottleneck_channels = int(out_channels * bottleneck_ratio)
    if strides < 2:
        c_hat, c = channel_split(inputs, '{}/spl'.format(prefix))
        inputs = c

    x = YoloConv2D(bottleneck_channels,
                   kernel_size=(1, 1),
                   strides=1,
                   padding='same',
                   name='{}/1x1conv_1'.format(prefix))(inputs)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='{}/bn_1x1conv_1'.format(prefix))(x)
    x = Activation('relu', name='{}/relu_1x1conv_1'.format(prefix))(x)
    x = YoloDepthwiseConv2D(kernel_size=3,
                            strides=strides,
                            padding='same',
                            name='{}/3x3dwconv'.format(prefix))(x)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='{}/bn_3x3dwconv'.format(prefix))(x)
    x = YoloConv2D(bottleneck_channels,
                   kernel_size=1,
                   strides=1,
                   padding='same',
                   name='{}/1x1conv_2'.format(prefix))(x)
    x = CustomBatchNormalization(axis=bn_axis,
                                 name='{}/bn_1x1conv_2'.format(prefix))(x)
    x = Activation('relu', name='{}/relu_1x1conv_2'.format(prefix))(x)

    if strides < 2:
        ret = Concatenate(axis=bn_axis,
                          name='{}/concat_1'.format(prefix))([x, c_hat])
    else:
        s2 = YoloDepthwiseConv2D(kernel_size=3,
                                 strides=2,
                                 padding='same',
                                 name='{}/3x3dwconv_2'.format(prefix))(inputs)
        s2 = CustomBatchNormalization(
            axis=bn_axis, name='{}/bn_3x3dwconv_2'.format(prefix))(s2)
        s2 = YoloConv2D(bottleneck_channels,
                        kernel_size=1,
                        strides=1,
                        padding='same',
                        name='{}/1x1_conv_3'.format(prefix))(s2)
        s2 = CustomBatchNormalization(
            axis=bn_axis, name='{}/bn_1x1conv_3'.format(prefix))(s2)
        s2 = Activation('relu', name='{}/relu_1x1conv_3'.format(prefix))(s2)
        ret = Concatenate(axis=bn_axis,
                          name='{}/concat_2'.format(prefix))([x, s2])

    ret = Lambda(channel_shuffle,
                 name='{}/channel_shuffle'.format(prefix))(ret)

    return ret