当前位置:   article > 正文

神经网络学习小记录38——MobileNetV3(large)模型的复现详解_mobilenetv3large

mobilenetv3large

学习前言

为了防止某位我的粉丝寒假没有办法正常工作,我赶紧看了看MobilenetV3。
在这里插入图片描述

什么是MobileNetV3

最新的MobileNetV3的被写在了论文《Searching for MobileNetV3》中。

它是mobilnet的最新版,据说效果还是很好的。

作为一种轻量级网络,它的参数量还是一如既往的小。

它综合了以下四个特点:
1、MobileNetV1的深度可分离卷积(depthwise separable convolutions)。
2、MobileNetV2的具有线性瓶颈的逆残差结构(the inverted residual with linear bottleneck)。
3、轻量级的注意力模型。
4、利用h-swish代替swish函数。

代码下载

https://github.com/bubbliiiing/classic-convolution-network

MobileNetV3(large)的网络结构

1、MobileNetV3(large)的整体结构

在这里插入图片描述
如何看懂这个表呢?我们从每一列出发:
第一列Input代表mobilenetV3每个特征层的shape变化;
第二列Operator代表每次特征层即将经历的block结构,我们可以看到在MobileNetV3中,特征提取经过了许多的bneck结构;
第三、四列分别代表了bneck内逆残差结构上升后的通道数、输入到bneck时特征层的通道数。
第五列SE代表了是否在这一层引入注意力机制。
第六列NL代表了激活函数的种类,HS代表h-swish,RE代表RELU。
第七列s代表了每一次block结构所用的步长。

2、MobileNetV3特有的bneck结构

bneck结构如下图所示:
在这里插入图片描述
它综合了以下四个特点:
a、MobileNetV2的具有线性瓶颈的逆残差结构(the inverted residual with linear bottleneck)。
在这里插入图片描述
即先利用1x1卷积进行升维度,再进行下面的操作,并具有残差边。

b、MobileNetV1的深度可分离卷积(depthwise separable convolutions)。
在这里插入图片描述
在输入1x1卷积进行升维度后,进行3x3深度可分离卷积。

c、轻量级的注意力模型。
在这里插入图片描述
这个注意力机制的作用方式是调整每个通道的权重。

d、利用h-swish代替swish函数。
在结构中使用了h-swishj激活函数,代替swish函数,减少运算量,提高性能。
在这里插入图片描述

网络实现代码

由于keras代码没有预训练权重,所以只是把网络结构po出来。

from keras.layers import Conv2D, DepthwiseConv2D, Dense, GlobalAveragePooling2D,Input
from keras.layers import Activation, BatchNormalization, Add, Multiply, Reshape
from keras.models import Model
from keras import backend as K

alpha = 1
def relu6(x):
    # relu函数
    return K.relu(x, max_value=6.0)

def hard_swish(x):
    # 利用relu函数乘上x模拟sigmoid
    return x * K.relu(x + 3.0, max_value=6.0) / 6.0

def return_activation(x, nl):
    # 用于判断使用哪个激活函数
    if nl == 'HS':
        x = Activation(hard_swish)(x)
    if nl == 'RE':
        x = Activation(relu6)(x)

    return x

def conv_block(inputs, filters, kernel, strides, nl):
    # 一个卷积单元,也就是conv2d + batchnormalization + activation
    channel_axis = 1 if K.image_data_format() == 'channels_first' else -1

    x = Conv2D(filters, kernel, padding='same', strides=strides)(inputs)
    x = BatchNormalization(axis=channel_axis)(x)

    return return_activation(x, nl)

def squeeze(inputs):
    # 注意力机制单元
    input_channels = int(inputs.shape[-1])

    x = GlobalAveragePooling2D()(inputs)
    x = Dense(int(input_channels/4))(x)
    x = Activation(relu6)(x)
    x = Dense(input_channels)(x)
    x = Activation(hard_swish)(x)
    x = Reshape((1, 1, input_channels))(x)
    x = Multiply()([inputs, x])

    return x

def bottleneck(inputs, filters, kernel, up_dim, stride, sq, nl):
    channel_axis = 1 if K.image_data_format() == 'channels_first' else -1

    input_shape = K.int_shape(inputs)

    tchannel = int(up_dim)
    cchannel = int(alpha * filters)

    r = stride == 1 and input_shape[3] == filters
    # 1x1卷积调整通道数,通道数上升
    x = conv_block(inputs, tchannel, (1, 1), (1, 1), nl)
    # 进行3x3深度可分离卷积
    x = DepthwiseConv2D(kernel, strides=(stride, stride), depth_multiplier=1, padding='same')(x)
    x = BatchNormalization(axis=channel_axis)(x)
    x = return_activation(x, nl)
    # 引入注意力机制
    if sq:
        x = squeeze(x)
    # 下降通道数
    x = Conv2D(cchannel, (1, 1), strides=(1, 1), padding='same')(x)
    x = BatchNormalization(axis=channel_axis)(x)


    if r:
        x = Add()([x, inputs])

    return x

def MobileNetv3_large(shape = (224,224,3),n_class = 1000):
    inputs = Input(shape)
    # 224,224,3 -> 112,112,16
    x = conv_block(inputs, 16, (3, 3), strides=(2, 2), nl='HS')
    x = bottleneck(x, 16, (3, 3), up_dim=16, stride=1, sq=False, nl='RE')
    # 112,112,16 -> 56,56,24
    x = bottleneck(x, 24, (3, 3), up_dim=64, stride=2, sq=False, nl='RE')
    x = bottleneck(x, 24, (3, 3), up_dim=72, stride=1, sq=False, nl='RE')
    
    # 56,56,24 -> 28,28,40
    x = bottleneck(x, 40, (5, 5), up_dim=72, stride=2, sq=True, nl='RE')
    x = bottleneck(x, 40, (5, 5), up_dim=120, stride=1, sq=True, nl='RE')
    x = bottleneck(x, 40, (5, 5), up_dim=120, stride=1, sq=True, nl='RE')

    # 28,28,40 -> 14,14,80
    x = bottleneck(x, 80, (3, 3), up_dim=240, stride=2, sq=False, nl='HS')
    x = bottleneck(x, 80, (3, 3), up_dim=200, stride=1, sq=False, nl='HS')
    x = bottleneck(x, 80, (3, 3), up_dim=184, stride=1, sq=False, nl='HS')
    x = bottleneck(x, 80, (3, 3), up_dim=184, stride=1, sq=False, nl='HS')

    # 14,14,80 -> 14,14,112
    x = bottleneck(x, 112, (3, 3), up_dim=480, stride=1, sq=True, nl='HS')
    x = bottleneck(x, 112, (3, 3), up_dim=672, stride=1, sq=True, nl='HS')

    # 14,14,112 -> 7,7,160
    x = bottleneck(x, 160, (5, 5), up_dim=672, stride=2, sq=True, nl='HS')
    x = bottleneck(x, 160, (5, 5), up_dim=960, stride=1, sq=True, nl='HS')
    x = bottleneck(x, 160, (5, 5), up_dim=960, stride=1, sq=True, nl='HS')
    
    # 7,7,160 -> 7,7,960
    x = conv_block(x, 960, (1, 1), strides=(1, 1), nl='HS')
    x = GlobalAveragePooling2D()(x)
    x = Reshape((1, 1, 960))(x)

    x = Conv2D(1280, (1, 1), padding='same')(x)
    x = return_activation(x, 'HS')

    x = Conv2D(n_class, (1, 1), padding='same', activation='softmax')(x)
    x = Reshape((n_class,))(x)

    model = Model(inputs, x)

    return model
if __name__ == "__main__":
    model = MobileNetv3_large()
    model.summary()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Monodyee/article/detail/385035
推荐阅读
相关标签
  

闽ICP备14008679号