mobile_mobilenet - CSDN
精华内容
参与话题
  • 神经网络学习小记录23——MobileNet模型的复现详解

    千次阅读 多人点赞 2019-11-13 10:37:28
    神经网络学习小记录23——MobileNet模型的复现详解学习前言什么是MobileNet模型Xception网络部分实现代码图片预测 学习前言 MobileNet是一种轻量级网络,相比于其它结构网络,它不一定是最准的,但是它真的很轻!...

    神经网络学习小记录23——MobileNet模型的复现详解

    学习前言

    MobileNet是一种轻量级网络,相比于其它结构网络,它不一定是最准的,但是它真的很轻!
    在这里插入图片描述

    什么是MobileNet模型

    MobileNet模型是Google针对手机等嵌入式设备提出的一种轻量级的深层神经网络,其使用的核心思想便是depthwise separable convolution。

    对于一个卷积点而言:
    假设有一个3×3大小的卷积层,其输入通道为16、输出通道为32。具体为,32个3×3大小的卷积核会遍历16个通道中的每个数据,最后可得到所需的32个输出通道,所需参数为16×32×3×3=4608个。

    应用深度可分离卷积,用16个3×3大小的卷积核分别遍历16通道的数据,得到了16个特征图谱。在融合操作之前,接着用32个1×1大小的卷积核遍历这16个特征图谱,所需参数为16×3×3+16×32×1×1=656个。
    可以看出来depthwise separable convolution可以减少模型的参数。

    如下这张图就是depthwise separable convolution的结构
    在这里插入图片描述
    在建立模型的时候,可以使用Keras中的DepthwiseConv2D层实现深度可分离卷积,然后再利用1x1卷积调整channels数。

    通俗地理解就是3x3的卷积核厚度只有一层,然后在输入张量上一层一层地滑动,每一次卷积完生成一个输出通道,当卷积完成后,在利用1x1的卷积调整厚度。

    如下就是MobileNet的结构,其中Conv dw就是分层卷积,在其之后都会接一个1x1的卷积进行通道处理,
    在这里插入图片描述

    MobileNet网络部分实现代码

    #-------------------------------------------------------------#
    #   MobileNet的网络部分
    #-------------------------------------------------------------#
    import warnings
    import numpy as np
    
    from keras.preprocessing import image
    
    from keras.models import Model
    from keras.layers import DepthwiseConv2D,Input,Activation,Dropout,Reshape,BatchNormalization,GlobalAveragePooling2D,GlobalMaxPooling2D,Conv2D
    from keras.applications.imagenet_utils import decode_predictions
    from keras import backend as K
    
    
    def MobileNet(input_shape=[224,224,3],
                  depth_multiplier=1,
                  dropout=1e-3,
                  classes=1000):
    
    
        img_input = Input(shape=input_shape)
    
        # 224,224,3 -> 112,112,32
        x = _conv_block(img_input, 32, strides=(2, 2))
    
        # 112,112,32 -> 112,112,64
        x = _depthwise_conv_block(x, 64, depth_multiplier, block_id=1)
    
        # 112,112,64 -> 56,56,128
        x = _depthwise_conv_block(x, 128, depth_multiplier,
                                  strides=(2, 2), block_id=2)
        # 56,56,128 -> 56,56,128
        x = _depthwise_conv_block(x, 128, depth_multiplier, block_id=3)
    
        # 56,56,128 -> 28,28,256
        x = _depthwise_conv_block(x, 256, depth_multiplier,
                                  strides=(2, 2), block_id=4)
        
        # 28,28,256 -> 28,28,256
        x = _depthwise_conv_block(x, 256, depth_multiplier, block_id=5)
    
        # 28,28,256 -> 14,14,512
        x = _depthwise_conv_block(x, 512, depth_multiplier,
                                  strides=(2, 2), block_id=6)
        
        # 14,14,512 -> 14,14,512
        x = _depthwise_conv_block(x, 512, depth_multiplier, block_id=7)
        x = _depthwise_conv_block(x, 512, depth_multiplier, block_id=8)
        x = _depthwise_conv_block(x, 512, depth_multiplier, block_id=9)
        x = _depthwise_conv_block(x, 512, depth_multiplier, block_id=10)
        x = _depthwise_conv_block(x, 512, depth_multiplier, block_id=11)
    
        # 14,14,512 -> 7,7,1024
        x = _depthwise_conv_block(x, 1024, depth_multiplier,
                                  strides=(2, 2), block_id=12)
        x = _depthwise_conv_block(x, 1024, depth_multiplier, block_id=13)
    
        # 7,7,1024 -> 1,1,1024
        x = GlobalAveragePooling2D()(x)
        x = Reshape((1, 1, 1024), name='reshape_1')(x)
        x = Dropout(dropout, name='dropout')(x)
        x = Conv2D(classes, (1, 1),padding='same', name='conv_preds')(x)
        x = Activation('softmax', name='act_softmax')(x)
        x = Reshape((classes,), name='reshape_2')(x)
    
        inputs = img_input
    
        model = Model(inputs, x, name='mobilenet_1_0_224_tf')
        model_name = 'mobilenet_1_0_224_tf.h5'
        model.load_weights(model_name)
    
        return model
    
    def _conv_block(inputs, filters, kernel=(3, 3), strides=(1, 1)):
        x = Conv2D(filters, kernel,
                   padding='same',
                   use_bias=False,
                   strides=strides,
                   name='conv1')(inputs)
        x = BatchNormalization(name='conv1_bn')(x)
        return Activation(relu6, name='conv1_relu')(x)
    
    
    def _depthwise_conv_block(inputs, pointwise_conv_filters,
                              depth_multiplier=1, strides=(1, 1), block_id=1):
    
        x = DepthwiseConv2D((3, 3),
                            padding='same',
                            depth_multiplier=depth_multiplier,
                            strides=strides,
                            use_bias=False,
                            name='conv_dw_%d' % block_id)(inputs)
    
        x = BatchNormalization(name='conv_dw_%d_bn' % block_id)(x)
        x = Activation(relu6, name='conv_dw_%d_relu' % block_id)(x)
    
        x = Conv2D(pointwise_conv_filters, (1, 1),
                   padding='same',
                   use_bias=False,
                   strides=(1, 1),
                   name='conv_pw_%d' % block_id)(x)
        x = BatchNormalization(name='conv_pw_%d_bn' % block_id)(x)
        return Activation(relu6, name='conv_pw_%d_relu' % block_id)(x)
    
    def relu6(x):
        return K.relu(x, max_value=6)
    

    图片预测

    建立网络后,可以用以下的代码进行预测。

    def preprocess_input(x):
        x /= 255.
        x -= 0.5
        x *= 2.
        return x
    
    
    if __name__ == '__main__':
        model = MobileNet(input_shape=(224, 224, 3))
    
        img_path = 'elephant.jpg'
        img = image.load_img(img_path, target_size=(224, 224))
        x = image.img_to_array(img)
        x = np.expand_dims(x, axis=0)
        x = preprocess_input(x)
        print('Input image shape:', x.shape)
    
        preds = model.predict(x)
        print(np.argmax(preds))
        print('Predicted:', decode_predictions(preds, 1))
    

    预测所需的已经训练好的Xception模型可以在https://github.com/fchollet/deep-learning-models/releases下载。非常方便。
    预测结果为:

    Predicted: [[('n02504458', 'African_elephant', 0.7590296)]]
    
    展开全文
  • 憨批的语义分割1——基于Mobile模型的segnet讲解

    千次阅读 热门讨论 2019-11-08 20:34:26
    憨批的语义分割1——基于Mobile模型的segnet讲解学习前言什么是Segnet模型segnet模型的代码实现1、主干模型Mobilenet。2、segnet的Decoder解码部分代码测试 学习前言 最近开始设计新的领域啦,语义分割也是图像处理...

    学习前言

    最近开始设计新的领域啦,语义分割也是图像处理一个非常重要的应用方向,我查了很多资料苦于如何入门,接下来给大家讲讲里面比较基础的segnet模型。在下一个BLOG我会跟大家讲怎么训练自己的segnet模型。

    在这里插入图片描述

    什么是Segnet模型

    Segnet模型是一个比较基础的语义分割模型,其结构比较简单,在说其结构之前,我们先讲一下convolutional Encoder-Decoder的结构。
    主要结构与自编码(Autoencoder)类似,通过编码解码复原图片上每一个点所属的类别。
    下图主要是说明利用卷积层编码与解码的过程。
    在这里插入图片描述
    segnet模型与上述模型类似。
    因为基于VGG模型的语义分割模型都太大了,我的电脑支撑不住,所以我用的主干网络都是mobile模型。
    其主要结构如图所示:
    在这里插入图片描述
    由结构可以看到,其利用Encoder中提取了多次特征的f4进行处理,利用Decoder进行多次上采样Upsampling2D。最后得到一个具有一定hw的filter数量为n_classes的图层。
    为什么filter要用n_classes呢,因为其代表的就是每个像素点所属的种类。

    这么一想其实语义分割是不是也没有那么难?

    用一句话概括就是 从主干模型中提取出卷积了多次,具有一定特征的层(典型的是hw经过了4次压缩后的层),然后利用UpSampling2D函数进行三次上采样,得到输出层(语句分割的结果)。

    segnet模型的代码实现

    segnet模型的代码分为两部分。

    1、主干模型Mobilenet。

    该部分用于特征提取,实际上就是常规的mobilenet结构,想要了解mobilenet结构的朋友们可以看看我的另一篇博客神经网络学习小记录23——MobileNet模型的复现详解

    from keras.models import *
    from keras.layers import *
    import keras.backend as K
    import keras
    
    IMAGE_ORDERING = 'channels_last'
    
    def relu6(x):
    	return K.relu(x, max_value=6)
    
    def _conv_block(inputs, filters, alpha, kernel=(3, 3), strides=(1, 1)):
    
    	channel_axis = 1 if IMAGE_ORDERING == 'channels_first' else -1
    	filters = int(filters * alpha)
    	x = ZeroPadding2D(padding=(1, 1), name='conv1_pad', data_format=IMAGE_ORDERING  )(inputs)
    	x = Conv2D(filters, kernel , data_format=IMAGE_ORDERING  ,
    										padding='valid',
    										use_bias=False,
    										strides=strides,
    										name='conv1')(x)
    	x = BatchNormalization(axis=channel_axis, name='conv1_bn')(x)
    	return Activation(relu6, name='conv1_relu')(x)
    
    def _depthwise_conv_block(inputs, pointwise_conv_filters, alpha,
    													depth_multiplier=1, strides=(1, 1), block_id=1):
    
    	channel_axis = 1 if IMAGE_ORDERING == 'channels_first' else -1
    	pointwise_conv_filters = int(pointwise_conv_filters * alpha)
    
    	x = ZeroPadding2D((1, 1) , data_format=IMAGE_ORDERING , name='conv_pad_%d' % block_id)(inputs)
    	x = DepthwiseConv2D((3, 3) , data_format=IMAGE_ORDERING ,
    														 padding='valid',
    														 depth_multiplier=depth_multiplier,
    														 strides=strides,
    														 use_bias=False,
    														 name='conv_dw_%d' % block_id)(x)
    	x = BatchNormalization(
    			axis=channel_axis, name='conv_dw_%d_bn' % block_id)(x)
    	x = Activation(relu6, name='conv_dw_%d_relu' % block_id)(x)
    
    	x = Conv2D(pointwise_conv_filters, (1, 1), data_format=IMAGE_ORDERING ,
    										padding='same',
    										use_bias=False,
    										strides=(1, 1),
    										name='conv_pw_%d' % block_id)(x)
    	x = BatchNormalization(axis=channel_axis,
    																name='conv_pw_%d_bn' % block_id)(x)
    	return Activation(relu6, name='conv_pw_%d_relu' % block_id)(x)
    
    def get_mobilenet_encoder( input_height=224 ,  input_width=224 , pretrained='imagenet' ):
    
    	alpha=1.0
    	depth_multiplier=1
    	dropout=1e-3
    
    
    	img_input = Input(shape=(input_height,input_width , 3 ))
    
    
    	x = _conv_block(img_input, 32, alpha, strides=(2, 2))
    	x = _depthwise_conv_block(x, 64, alpha, depth_multiplier, block_id=1) 
    	f1 = x
    
    	x = _depthwise_conv_block(x, 128, alpha, depth_multiplier,
    														strides=(2, 2), block_id=2)  
    	x = _depthwise_conv_block(x, 128, alpha, depth_multiplier, block_id=3) 
    	f2 = x
    
    	x = _depthwise_conv_block(x, 256, alpha, depth_multiplier,
    														strides=(2, 2), block_id=4)  
    	x = _depthwise_conv_block(x, 256, alpha, depth_multiplier, block_id=5) 
    	f3 = x
    
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier,
    														strides=(2, 2), block_id=6) 
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=7) 
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=8) 
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=9) 
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=10) 
    	x = _depthwise_conv_block(x, 512, alpha, depth_multiplier, block_id=11) 
    	f4 = x 
    
    	x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier,
    														strides=(2, 2), block_id=12)  
    	x = _depthwise_conv_block(x, 1024, alpha, depth_multiplier, block_id=13) 
    	f5 = x 
    
    	return img_input , [f1 , f2 , f3 , f4 , f5 ]
    

    2、segnet的Decoder解码部分

    这一部分对应着上面segnet模型中的解码部分。
    其关键就是把获得的特征重新映射到比较大的图中的每一个像素点,用于每一个像素点的分类。

    from keras.models import *
    from keras.layers import *
    from nets.mobilenet import get_mobilenet_encoder
    
    IMAGE_ORDERING = 'channels_last'
    def segnet_decoder(  f , n_classes , n_up=3 ):
    
    	assert n_up >= 2
    
    	o = f
    	o = ( ZeroPadding2D( (1,1) , data_format=IMAGE_ORDERING ))(o)
    	o = ( Conv2D(512, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)
    	o = ( BatchNormalization())(o)
    	# 进行一次UpSampling2D,此时hw变为原来的1/8
    	# 52,52,512
    	o = ( UpSampling2D( (2,2), data_format=IMAGE_ORDERING))(o)
    	o = ( ZeroPadding2D( (1,1), data_format=IMAGE_ORDERING))(o)
    	o = ( Conv2D( 256, (3, 3), padding='valid', data_format=IMAGE_ORDERING))(o)
    	o = ( BatchNormalization())(o)
    
    	# 进行一次UpSampling2D,此时hw变为原来的1/4
    	# 104,104,256
    	for _ in range(n_up-2):
    		o = ( UpSampling2D((2,2)  , data_format=IMAGE_ORDERING ) )(o)
    		o = ( ZeroPadding2D((1,1) , data_format=IMAGE_ORDERING ))(o)
    		o = ( Conv2D( 128 , (3, 3), padding='valid' , data_format=IMAGE_ORDERING ))(o)
    		o = ( BatchNormalization())(o)
    
    	# 进行一次UpSampling2D,此时hw变为原来的1/2
    	# 208,208,128
    	o = ( UpSampling2D((2,2)  , data_format=IMAGE_ORDERING ))(o)
    	o = ( ZeroPadding2D((1,1)  , data_format=IMAGE_ORDERING ))(o)
    	o = ( Conv2D( 64 , (3, 3), padding='valid'  , data_format=IMAGE_ORDERING ))(o)
    	o = ( BatchNormalization())(o)
    
    	# 此时输出为h_input/2,w_input/2,nclasses
    	o =  Conv2D( n_classes , (3, 3) , padding='same', data_format=IMAGE_ORDERING )( o )
    	
    	return o 
    
    def _segnet( n_classes , encoder  ,  input_height=416, input_width=608 , encoder_level=3):
    	# encoder通过主干网络
    	img_input , levels = encoder( input_height=input_height ,  input_width=input_width )
    
    	# 获取hw压缩四次后的结果
    	feat = levels[encoder_level]
    
    	# 将特征传入segnet网络
    	o = segnet_decoder(feat, n_classes, n_up=3 )
    
    	# 将结果进行reshape
    	o = Reshape((int(input_height/2)*int(input_width/2), -1))(o)
    	o = Softmax()(o)
    	model = Model(img_input,o)
    
    	return model
    
    def mobilenet_segnet( n_classes ,  input_height=224, input_width=224 , encoder_level=3):
    
    	model = _segnet( n_classes , get_mobilenet_encoder ,  input_height=input_height, input_width=input_width , encoder_level=encoder_level)
    	model.model_name = "mobilenet_segnet"
    	return model
    

    代码测试

    将上面两个代码分别保存为mobilenet.py和segnet.py。按照如下方式存储:
    在这里插入图片描述
    (忽略其中的predict.py,那是下一个blog讲怎么训练的时候用的。)
    此时我们运行test.py的代码:

    from nets.segnet import mobilenet_segnet
    
    model = mobilenet_segnet(2,input_height=416,input_width=416)
    model.summary()
    

    如果没有出错的话就会得到如下的结果:
    在这里插入图片描述
    到这里就完成了基于Mobile模型的segnet的搭建。

    展开全文
  • 神经网络学习小记录39——MobileNetV3(small)模型的复现详解学习前言什么是MobileNetV3large与small的区别MobileNetV3(small)的网络结构1、MobileNetV3(small)的整体结构2、MobileNetV3特有的bneck结构网络...

    学习前言

    不知道咋地,就是突然想把small也一起写了。
    在这里插入图片描述

    什么是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

    large与small的区别

    其实MobileNetV3中的large与small模型没有特别大的区别,主要的区别是通道数的变化与bneck的次数。

    MobileNetV3(small)的网络结构

    1、MobileNetV3(small)的整体结构

    在这里插入图片描述
    如上为MobileNetV3(small)的表,与MobileNetV3(large)相比,bneck的次数与通道数都有一定的下降。

    如何看懂这个表呢?我们从每一列出发:
    第一列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_small(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')
    
        # 112,112,16 -> 56,56,16
        x = bottleneck(x, 16, (3, 3), up_dim=16, stride=2, sq=True, nl='RE')
    
        # 56,56,16 -> 28,28,24
        x = bottleneck(x, 24, (3, 3), up_dim=72, stride=2, sq=False, nl='RE')
        x = bottleneck(x, 24, (3, 3), up_dim=88, stride=1, sq=False, nl='RE')
        
        # 28,28,24 -> 14,14,40
        x = bottleneck(x, 40, (5, 5), up_dim=96, stride=2, sq=True, nl='HS')
        x = bottleneck(x, 40, (5, 5), up_dim=240, stride=1, sq=True, nl='HS')
        x = bottleneck(x, 40, (5, 5), up_dim=240, stride=1, sq=True, nl='HS')
        # 14,14,40 -> 14,14,48
        x = bottleneck(x, 48, (5, 5), up_dim=120, stride=1, sq=True, nl='HS')
        x = bottleneck(x, 48, (5, 5), up_dim=144, stride=1, sq=True, nl='HS')
    
        # 14,14,48 -> 7,7,96
        x = bottleneck(x, 96, (5, 5), up_dim=288, stride=2, sq=True, nl='HS')
        x = bottleneck(x, 96, (5, 5), up_dim=576, stride=1, sq=True, nl='HS')
        x = bottleneck(x, 96, (5, 5), up_dim=576, stride=1, sq=True, nl='HS')
    
        x = conv_block(x, 576, (1, 1), strides=(1, 1), nl='HS')
        x = GlobalAveragePooling2D()(x)
        x = Reshape((1, 1, 576))(x)
    
        x = Conv2D(1024, (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_small()
        model.summary()
    
    
    展开全文
  • MobileNet v1 和 v2

    千次阅读 2020-03-03 21:09:14
    1 MobileNet V1 MobileNet是针对移动端优化的卷积,所以当需要压缩模型时,可以考虑使用MobileNet替换卷积。下面我们开始学习MobileNet原理,并且先通过Tensorflow函数接口实现MobileNet,再手写python代码实现...

    1 MobileNet V1

    MobileNet是针对移动端优化的卷积,所以当需要压缩模型时,可以考虑使用MobileNet替换卷积。下面我们开始学习MobileNet原理,并且先通过Tensorflow函数接口实现MobileNet,再手写python代码实现MobileNet。

    1.1 普通卷积

    MobileNet是用于替换普通卷积,相比普通卷积,MobileNet参数更少,计算速度更快。我们先看一下输入为(h=12,w=12,c=4),卷积为3*3,输出为(h=12,w=12,c=2)前向计算中,普通卷积的参数量、乘法计算次数。普通卷积如下图所示: 

    普通卷积

     
    从上图可以很简单的计算到,普通卷积参数总数为72个,需要做10368次乘法计算。

    1.2 MobileNet v1

    相比普通卷积,MobileNet采用的方法是,将卷积分解为2个操作:depthwise和pointwise。pointwise比较容易理解,就是普通的卷积核为1*1的卷积。depthwise采用的方法不是普通卷积方式,我们知道,对于输入通道数为4的feature map在计算卷积时,输出的每个通道都需要对应4个3*3卷积核参数。这一步是最主要的耗时,为了提升计算速度,MobileNet把每个输入feature map对应一个3*3卷积核,输出通道数不变,即为4。而真正对通道数做改变的是在pointwise,也就是1*1的卷积。

    下面图很清晰的理解mobilenet原理:

    mobilenet

    从上图可以很简单的计算到,普通卷积参数总数为44个,需要做6336次乘法计算。可以看到,mobilenet的参数和乘法计算次数明显比普通卷积要小。这还仅仅是我列举的简单例子,在实际网络中,几十层的网络很常见,feature map也是远远大于12*12*4。根据我的经验,普通100M的网络模型,将所有卷积替换成mobilenet后,能降到20M以下,计算速度更是不在一个量级。

    Mobilenet v2

    主要贡献

    有2点

    1,提出了逆向的残差结构(Inverted residuals)

    由于MobileNetV2版本使用了残差结构,和resnet的残差结构有异曲同工之妙,源于resnet,却和而不同。

     

    由于Resnet没有使用depthwise conv,所以,在进入pointwise conv之前的特征通道数是比较多的,所以,残差模块中使用了0.25倍的降维。而MobileNet v2由于有depthwise conv,通道数相对较少,所以残差中使用 了6倍的升维。

    总结起来,2点区别

    (1)ResNet的残差结构是0.25倍降维,MobileNet V2残差结构是6倍升维

    (2)ResNet的残差结构中3*3卷积为普通卷积,MobileNet V2中3*3卷积为depthwise conv

    MobileNet v1,MobileNet v2 的区别

    有2点

     

    (1)v2版本在进入3*3卷积之前,先进行了1*1pointwise conv升维,并且经过RELU。

    (2)1*1卷积出去后,没有进行RELU操作

    MobileNet v1,MobileNet v2 的实际使用区别:

    精度上,MobileNet v2优于MobileNet v1

    速度上,在GPU有并行的情况下,v1和v2速度基本差不多,在cpu这种无并行的情况下,v2要比v1慢大概40%。就是说,v2比v1的乘加运算量确实是小,但是最终速度是由好多因素决定的,这也就是shuffle v2的改进由来。

    MobileNet v1,MobileNet v2 的实际使用区别:

    精度上,MobileNet v2优于MobileNet v1

    速度上,在GPU有并行的情况下,v1和v2速度基本差不多,在cpu这种无并行的情况下,v2要比v1慢大概40%。就是说,v2比v1的乘加运算量确实是小,但是最终速度是由好多因素决定的,这也就是shuffle v2的改进由来。

    2,提出了线性瓶颈单元(linear bottlenecks)

    Why no RELU?

    首选看看RELU的功能。RELU可以将负值全部映射为0,具有高度非线性。下图为论文的测试。在维度比较低2,3的时候,使用RELU对信息的损失是比较严重的。而单维度比较高15,30时,信息的损失是比较少的。

     

    MobileNet v2中为了保证信息不被大量损失,应此在残差模块中去掉最后一个的RELU。因此,也称为线性模块单元。

     

    MobileNet v2网络结构:

     

    其中,t表示通道的扩大系数expansion factor,c表示输出通道数,

    n表示该单元重复次数,s表示滑动步长stride

     

    其中bottleneck模块中,stride=1和stride=2的模块分别如上图所示,只有stride=1的模块才有残差结构。 

    结果:

    MobileNet v2速度和准确性都优于MobileNet v1

    和其他结构的对比:

    相关论文

     

    相关中文论文
    邢艳芳,卓文鑫,段红秀. 基于MobileNet的敏感图像识别系统设计[J]. 电视技术, 2018, 42(7):53-56.
    童星,张激. 基于SSD_MobileNet模型的ROS平台目标检测[J]. 计算机系统应用, 2019, 28(1):94-99.
    曹香滢,孙卫民,朱悠翔 . 基于科优先策略的植物图像识别[J]. 计算机应用, 2018, 38(11):195-199.
    黄宁波. 用于目标检测的深度学习算法优化研究[D]. 长春理工大学, 2018.
    杨洁.基于卷积神经网络的目标检测研究[D]. 南华大学, 2018.

    引用:

    https://blog.csdn.net/qq_14845119/article/details/73648100

    https://blog.csdn.net/huachao1001/article/details/79171447

    展开全文
  • MobileNetV1 & MobileNetV2 简介

    万次阅读 多人点赞 2020-07-10 15:24:39
    一、参数数量和理论计算量 1、定义 参数数量(params):关系到模型大小,单位通常为M,通常参数用 float32 表示,所以模型大小是参数数量的 4 倍 理论计算量(FLOPs): ...是 floating point operations 的...
  • mobile.zip

    2020-06-07 14:24:46
    discuz论坛多端应用源码之后端插件 使用discuz论坛作为后端生成微信、QQ、支付宝、头条抖音及百度小程序,并支持安卓或苹果APP.
  • [原创首发] js手机移动端选择插件 mobileSelect.js

    万次阅读 多人点赞 2017-09-27 23:35:07
    mobileSelect.js一款多功能的手机移动端选择组件,支持单选到多选、支持多级级联、提供自定义回调函数、提供update函数二次渲染、重定位函数、兼容pc端拖拽等等。mobileSelect.js是一个js移动端选择控件,不依赖任何...
  • vue-mobile - 一个基于VUE的UI框架

    万次阅读 2016-07-09 17:55:32
    我对UI框架的一些想法最近一年多一直在做UI库,从 SUI Mobile -> Light7 -> jQuery WeUI。自己也在做的过程中对UI库类的产品有了更深入的认识,SUI Mobile 和 Light7 有一个很大的问题在于:试图用一个轻量的基于...
  • antd-mobile的listView踩坑笔记

    万次阅读 热门讨论 2019-08-31 12:08:23
    于是就用到了antd的antd-mobile的listView组件。但是遇到了很多坑,今天总结出来分享给大家。 一:数据已经全部展示了却还是重复渲染。 原因: 自己太二,在componentWillReceiveProps 里面做了俩个判断执行了俩次...
  • 为什么项目中不使用jquerymobile

    千次阅读 2015-07-30 15:20:25
    这段时间一直在忙着做手机版和微信版预约,由于公司没有专业的美工,所以就在网上找了手机端的前端框架jquerymobile,由于公司没有jquerymobile的使用经验,基本上是边开发边学习,用到的效果现查先用。但是在实际...
  • WIN10 windows mobile设备中心连接不上

    千次阅读 2019-08-08 15:44:49
    WIN10下windows mobile设备中心连接不上 网上的教程都是把基于Windows mobile2003的设备连接里的登录身份改为本地系统账户。 这个必须是要之前设备成功连接上电脑改了才会有效,不然会发现还是连不上。 其实还要把...
  • 泛微E-Mobile4.5服务端安装手册

    万次阅读 2015-06-15 10:07:06
    1.本文档只做为E-mobile4.5服务器端安装配置手册! 2.E-Mobile4.5可运行在windows和linux服务器上 3.E-Mobile4.5必须与ecology服务器互联,因此, Ø 请确保在E-Mobile所在的服务器上可以通过浏览器访问Ecology...
  • jquerymobile设计完整例子

    千次下载 热门讨论 2020-07-30 23:32:24
    jquerymobile例子 包含从登陆到菜单和各种菜单切换完整设计 上传只为分享
  • ant-design-mobile框架踩坑(一)

    万次阅读 2018-12-04 15:42:31
    一直在用ant.design桌面版,现在退出了移动版,必须研究一下,但是这不看不要紧,一看就遇到了好多坑,好多坑···1....$ dva new mobileApp创建完成后,已经是npm install过了,所以不需要重新下载依赖。
  • jQuery Mobile修改button的内容

    千次阅读 2015-02-02 16:18:08
    jQuery Mobile修改button的内容。 使用jQuery Mobile也有一段时间了,最近同事提出,他需要更改button的内容,但是修改不了。我也试着修改了几次,button的内容其实是更改了,但是页面并未刷新。在调试中使用了...
  • 在使用jQuery Mobile开发时,有时候我们需要在请求ajax期间,显示加载提示框(例如:一个旋转图片+一个提示:加载中...)。这个时候,我们可以手动显示jQuery Mobile的加载器,大致流程如下: 1. 启动加载器,显示...
  • windows键+R打开【运行】(或者你手动查找),输入services.msc,在服务上找到这两个服务:Windows Mobile 的设备 和 基于 Windows Mobile 2003 的设备连接,右键这两个服务,启动类型原来的 自动(延迟启动)或...
  • jQuery.mobile.changePage方法用的还是很多的。作为一个老手,有必要对jQuery mobile中实用方法做一些总结。系列文章请看jQuery Mobile专栏。jquery.mobile.changepage是过时的jQuery Mobile 1.4.0及将被删除在1.5.0...
  • 滑动手势在移动设备是很流行的,在移动设备中滑动翻页中很常见 虽然这个功能可以在jQueryMobile中实现,但是个人与之前写的《【jQuery】论手机浏览器中拖拽动作的艰难性》(点击...那么,使用jQueryMobile实现滑动翻页
  • jQuery Mobile简单使用说明1.0.a1

    千次阅读 2014-10-29 15:01:27
    jQuery Mobile使用指南 简介:jQuery Mobile框架可以轻松的帮助我们实现非常好看的、可跨设备的Web应用程序。我们将后续的介绍中向大家介绍大量的代码及实例。 jQuery一直以来都是非常流行的富客户端及Web...
1 2 3 4 5 ... 20
收藏数 302,296
精华内容 120,918
关键字:

mobile