以下是MobileNetV3的神经网络模型实现,使用了Keras框架:

from keras import layers
from keras.models import Model


def _make_divisible(v, divisor, min_value=None):
    """
    This function is taken from the original tf repo.
    It ensures that all layers have a channel number that is divisible by 8
    It can be seen here:
    https://github.com/tensorflow/models/blob/master/research/slim/nets/mobilenet/mobilenet.py
    """
    if min_value is None:
        min_value = divisor
    new_v = max(min_value, int(v + divisor / 2) // divisor * divisor)
    # Make sure that round down does not go down by more than 10%.
    if new_v < 0.9 * v:
        new_v += divisor
    return new_v


def _relu6(x):
    """Relu 6
    """
    return layers.ReLU(max_value=6)(x)


def _hard_swish(x):
    """Hard swish
    """
    return layers.Multiply()([layers.Activation(_relu6)(x), x])


def _conv_block(inputs, filters, kernel, strides):
    """Convolution Block
    This function defines a 2D convolution operation with BN and relu6.
    # Arguments
        inputs: Tensor, input tensor of conv layer.
        filters: Integer, the dimensionality of the output space.
        kernel: An integer or tuple/list of 2 integers, specifying the width and
                height of the 2D convolution window.
        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.
    # Returns
        Output tensor.
    """
    channel_axis = 1 if layers.K.image_data_format() == 'channels_first' else -1
    filters = _make_divisible(filters, 8)
    x = layers.Conv2D(filters, kernel, padding='same', strides=strides, kernel_initializer='he_normal', use_bias=False)(inputs)
    x = layers.BatchNormalization(axis=channel_axis)(x)
    return layers.Activation(_relu6)(x)


def _bottleneck(inputs, filters, kernel, up_dim, stride, use_se):
    """Bottleneck
    This function defines a basic bottleneck structure.
    # Arguments
        inputs: Tensor, input tensor of conv layer.
        filters: Integer, the dimensionality of the output space.
        kernel: An integer or tuple/list of 2 integers, specifying the width and
                height of the 2D convolution window.
        up_dim: Integer, scaling ratio for the upsample layer.
        stride: 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.
        use_se: Boolean, whether to use SE module.
    # Returns
        Output tensor.
    """
    channel_axis = 1 if layers.K.image_data_format() == 'channels_first' else -1
    filters = _make_divisible(filters, 8)
    up_pointwise_filters = _make_divisible(up_dim, 8)
    x = _conv_block(inputs, up_pointwise_filters, (1, 1), (1, 1))

    x = layers.DepthwiseConv2D(kernel, strides=(stride, stride), depthwise_initializer='he_normal', padding='same', use_bias=False)(x)
    x = layers.BatchNormalization(axis=channel_axis)(x)
    x = layers.Activation(_relu6)(x)

    if use_se:
        x = _se_block(x, filters)

    x = layers.Conv2D(filters, (1, 1), padding='same', use_bias=False, kernel_initializer='he_normal')(x)
    x = layers.BatchNormalization(axis=channel_axis)(x)

    if stride == 1 and x.shape[channel_axis] == inputs.shape[channel_axis]:
        x = layers.Add()([x, inputs])
    return x


def _se_block(inputs, filters):
    """Squeeze and Excitation block
    This function defines a squeeze and excitation block.
    # Arguments
        inputs: Tensor, input tensor of conv layer.
        filters: Integer, the dimensionality of the output space.
    # Returns
        Output tensor.
    """
    channel_axis = 1 if layers.K.image_data_format() == 'channels_first' else -1
    se_shape = (1, 1, filters)
    se = layers.GlobalAveragePooling2D()(inputs)
    se = layers.Reshape(se_shape)(se)
    se = layers.Conv2D(filters // 4, (1, 1), padding='same', activation=_relu6, kernel_initializer='he_normal', use_bias=False)(se)
    se = layers.Conv2D(filters, (1, 1), padding='same', activation='sigmoid', kernel_initializer='he_normal', use_bias=False)(se)
    x = layers.Multiply()([inputs, se])
    return x


def MobileNetV3Small(input_shape, num_classes):
    """MobileNetv3 small model
    This function defines a MobileNetv3 small model.
    # Arguments
        input_shape: An integer or tuple/list of 3 integers, shape
                      of input tensor.
        num_classes: Number of classes.
    # Returns
        MobileNetv3 small model.
    """
    inputs = layers.Input(shape=input_shape)
    x = _conv_block(inputs, 16, (3, 3), strides=(2, 2))
    x = _bottleneck(x, 16, (3, 3), up_dim=16, stride=2, use_se=False)

    x = _bottleneck(x, 24, (3, 3), up_dim=72, stride=2, use_se=False)
    x = _bottleneck(x, 24, (3, 3), up_dim=88, stride=1, use_se=False)

    x = _bottleneck(x, 40, (5, 5), up_dim=96, stride=2, use_se=True)
    x = _bottleneck(x, 40, (5, 5), up_dim=240, stride=1, use_se=True)
    x = _bottleneck(x, 40, (5, 5), up_dim=240, stride=1, use_se=True)

    x = _bottleneck(x, 48, (5, 5), up_dim=120, stride=1, use_se=True)
    x = _bottleneck(x, 48, (5, 5), up_dim=144, stride=1, use_se=True)

    x = _bottleneck(x, 96, (5, 5), up_dim=288, stride=2, use_se=True)
    x = _bottleneck(x, 96, (5, 5), up_dim=576, stride=1, use_se=True)
    x = _bottleneck(x, 96, (5, 5), up_dim=576, stride=1, use_se=True)

    x = _conv_block(x, 576, (1, 1), strides=(1, 1))
    x = layers.GlobalAveragePooling2D()(x)
    x = layers.Reshape((1, 1, 576))(x)

    x = layers.Conv2D(1024, (1, 1), padding='same', use_bias=False, kernel_initializer='he_normal')(x)
    x = layers.BatchNormalization()(x)
    x = layers.Activation(_hard_swish)(x)

    x = layers.Conv2D(num_classes, (1, 1), padding='same', kernel_initializer='he_normal')(x)
    x = layers.Flatten()(x)
    x = layers.Activation('softmax')(x)

    model = Model(inputs, x)
    return model
使用keras框架,给出MobileNetV3的神经网络模型实现

原文地址: https://www.cveoy.top/t/topic/zFE 著作权归作者所有。请勿转载和采集!

免费AI点我,无需注册和登录