tensorflow2.2_MobilenetV1网络解析

1. MobilenetV1介绍

MobilenetV1是Google提出的用于移动和嵌入式应用的高效网络模型。MobilenetV1基于一种流线型的架构,使用深度可分离卷积来构建轻量级的深度神经网络。

2. 深度可分离卷积

MobileNetV1模型基于深度可分卷积这是一种分解卷积的形式,它将一个标准卷积分解为深度卷积和一个1×1卷积,1x1卷积又叫称为点卷积

在这里插入图片描述

标准的卷积是输入一个 D F D_{F} DF x D F D_{F} DF x M M M 的特征图,输出一个 D F D_{F} DF x D F D_{F} DF x N N N 的特征图。

标准的卷积层的参数是 D K D_{K} DK x D K D_{K} DK x M M M x N N N ,其中 D K D_{K} DK是卷积核的小大, M M M是输入通道数, N N N是输出通道数。

所以标准的卷积计算量如下:
D K D_{K} DK x D K D_{K} DK x M M M x N N N x D F D_{F} DF x D F D_{F} DF

深度可分离卷积由两层组成:深度卷积和点卷积。

我们使用深度卷积来为每个输入通道(输入深度)应用一个过滤器。然后使用点态卷积(一个简单的1×1卷积)创建深度层输出的线性组合。

其计算量为: D K D_{K} DK x D K D_{K} DK x M M M x D F D_{F} DF x D F D_{F} DF

相对于标准卷积,深度卷积是非常有效的。然而,它只过滤输入通道,并没有将它们组合起来创建新的功能。因此,为了生成这些新特征,需要一个额外的层,通过1 × 1的卷积计算深度卷积输出的线性组合。

其计算量为: M M M x N N N x D F D_{F} DF x D F D_{F} DF

例子:
标准卷积:
假设有一个56 x 56 x 16的特征图,其卷积核是3 x 3大小,输出通道为32,计算量大小就是56 x56 x16 x 32 x 3 x 3 = 14450688
深度可分离卷积:
假设有一个56 x 56 x 16的特征图,输出通道为32,先用16个3 x 3大小的卷积核进行卷积,接着用32个1 x 1大小的卷积核分别对这用16个3 x 3大小的卷积核进行卷积之后的特征图进行卷积,计算量为3 x 3 x 16 x 56 x 56 + 16 x 32 x 56 x 56 = 2057216

从而可见计算量少了许多。

3. 网络结构

在这里插入图片描述
其中其中Conv dw就是深度可分离卷积

4. 实现代码

from os import name
import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import (
    Activation, BatchNormalization, Conv2D, DepthwiseConv2D, Dropout,
    GlobalAveragePooling2D, Input, Reshape
)
from tensorflow.keras.models import Model
from plot_model import plot_model
from tensorflow.keras import backend as K

def relu6(x):
    return K.relu(x, max_value=6)

def Conv2D_block(inputs, filters, alpha, kernel_size=(3, 3), strides=(1, 1)):
    filters = int(filters * alpha)
    x = Conv2D(
        filters=filters, kernel_size=kernel_size, padding='same',
        use_bias=False, strides=strides, name='Conv'
    )(inputs)
    x = BatchNormalization(name='Conv_bn')(x)
    x = Activation(relu6, name='Conv_relu6')(x)

    return x

def Depthwise_Conv2D_block(inputs, filters, alpha, depth_multiplier=1, strides=(1, 1), block_id=1):
    filters = int(filters * alpha)
    x = DepthwiseConv2D(kernel_size=(3, 3), padding='same', depth_multiplier=depth_multiplier, strides=strides,
                        use_bias=False, name=f'Conv2D_dw_{block_id}')(inputs)
    
    x = BatchNormalization(name=f'Conv2D_dw_bn{block_id}')(x)
    x = Activation(relu6, name=f'Conv2D_dw_relu6{block_id}')(x)
    x = Conv2D(filters=filters, kernel_size=(1, 1), padding='same', strides=(1, 1), use_bias=False, name=f'Conv2D_1x1{block_id}')(x)
    x = BatchNormalization(name=f'Conv2D_pw_bn{block_id}')(x)
    x = Activation(relu6, name=f'Conv2D_pw_relu6{block_id}')(x)

    return x
    
def MobilenetV1(inputs, alpha=1.0, depth_multiplier=1, dropout=1e-3, classes=17):
    x = Conv2D_block(inputs=inputs, filters=32, alpha=alpha, strides=(2, 2))
    x = Depthwise_Conv2D_block(inputs=x, filters=64, alpha=alpha, depth_multiplier=depth_multiplier, block_id=1)
    
    x = Depthwise_Conv2D_block(inputs=x, strides=(2, 2), filters=128, alpha=alpha, depth_multiplier=depth_multiplier, block_id=2)
    x = Depthwise_Conv2D_block(inputs=x, filters=128, alpha=alpha, depth_multiplier=depth_multiplier, block_id=3)
    
    x = Depthwise_Conv2D_block(inputs=x, strides=(2, 2), filters=256, alpha=alpha, depth_multiplier=depth_multiplier, block_id=4)
    x = Depthwise_Conv2D_block(inputs=x, filters=256, alpha=alpha, depth_multiplier=depth_multiplier, block_id=5)
    
    x = Depthwise_Conv2D_block(inputs=x, strides=(2, 2), filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=6)
    x = Depthwise_Conv2D_block(inputs=x, filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=7)
    x = Depthwise_Conv2D_block(inputs=x, filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=8)
    x = Depthwise_Conv2D_block(inputs=x, filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=9)
    x = Depthwise_Conv2D_block(inputs=x, filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=10)
    x = Depthwise_Conv2D_block(inputs=x, filters=512, alpha=alpha, depth_multiplier=depth_multiplier, block_id=11)
    
    x = Depthwise_Conv2D_block(inputs=x, strides=(2, 2), filters=1024, alpha=alpha, depth_multiplier=depth_multiplier, block_id=12)
    x = Depthwise_Conv2D_block(inputs=x, filters=1024, alpha=alpha, depth_multiplier=depth_multiplier, block_id=13)

    x = GlobalAveragePooling2D()(x)

    shape = (1, 1, int(1024 * alpha))

    x = Reshape(shape, 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)
    
    return x
    

if __name__ == '__main__':
    is_show_picture = False
    inputs = Input(shape=(224,224,3))
    classes = 1000
    model = Model(inputs=inputs, outputs=MobilenetV1(inputs=inputs, classes=classes))
    
    model.summary()
    print(len(model.layers))
    for i in range(len(model.layers)):
        print(i, model.layers[i])
    if is_show_picture:
        plot_model(model,
           to_file='./nets_picture/MobilenetV1.png',
           )
        print("plot_model------------------------>")
    
    
    
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值