深度学习之图像分类(十)--MobileNetV1 网络结构

深度学习之图像分类(十)MobileNetV1 网络结构

本节学习 MobileNetV1 网络结构。学习视频源于 Bilibili,感谢霹雳吧啦Wz,建议大家去看视频学习哦。

请添加图片描述

1. 前言

在传统卷积神经网络中,内存需求大,运算量打,导致无法在移动设备以及嵌入式设备上运行,例如在手机上等等。VGG16 大概有 490M 模型参数,ResNet152 大概有 644M 模型参数。为了服务于社会,网络不能仅仅停留在实验室。为了推动神经网络应用于现实世界,MobileNet 氤氲而生。

MobileNet 是由google团队在 2017 年提出的,专注于移动端或者嵌入式设备中的轻量级 CNN 网络。相比于传统的卷积神经网络而言,在准确率小幅降低的前提下,大大减少了模型的参数与运算量。MobileNetV1 相比 VGG16 准确率低了 0.9%,但是模型参数量仅仅有 1/32。其原始论文为 MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications

MobileNetV1 网络中的亮点包括:

  • Depthwise Convolution 大大减少运算量以及参数量
  • 增加超参数 α , β \alpha, \beta α,β α \alpha α 控制卷积层卷积核数量, β \beta β 控制输入图像大小,都是人为自己设定的

2. DW 卷积

在传统卷积中,卷积核的channel与输入特征矩阵的channel是一致的,卷积核的个数对应于输出特征矩阵的channel。而在 DW 卷积中,每个卷积核的 channel 都是为 1 的,也就是对输入特征图的每一个 channel 单独进行卷积。既然每一个卷积核负责输入通道的一个 channel,那么卷积核的个数就是输入通道 channel 的个数,输出特征图通道 channel 数也和输入特征矩阵的通道 channel 数一致。如果要升通道数,那就 n 个卷积核对应一个输入矩阵的 channel,输出矩阵的通道数为输入矩阵通道数的 n 倍。这其实就是 group 数等于输入通道数的组卷积。但是实际上,mobileNet 是靠 PW 卷积去升通道数的。

请添加图片描述

3. Depthwise Separable Conv 深度可分卷积操作

Depthwise Separable Conv 由两部分组成,DW 卷积以及 PW 卷积。其实 PW 卷积就是 1 × 1 1 \times 1 1×1 卷积。先通过 DW 卷积,再通过 PW 卷积。
请添加图片描述

Depthwise Separable Conv 能节省多少参数呢?我们来做一个计算。普通卷积的计算量为 D k × D k × M × N × D F × D F D_k \times D_k \times M \times N \times D_F \times D_F Dk×Dk×M×N×DF×DF, 而先使用 DW 卷积,再使用 PW 卷积的计算量为 D k × D k × M × D F × D F + M × N × D F × D F D_k \times D_k \times M \times D_F \times D_F + M \times N \times D_F \times D_F Dk×Dk×M×DF×DF+M×N×DF×DF。所以说理论上其为普通卷积的 1 N + 1 D k 2 \frac{1}{N} + \frac{1}{D_k^2} N1+Dk21,通常 D k = 3 D_k = 3 Dk=3,即使用 3 × 3 3 \times 3 3×3 卷积,而 N N N 通常为几十上百,所以理论上普通卷积计算量为 DW + PW 的 8 到 9 倍。

请添加图片描述

(悄悄说,我们最近的研究中,正交构造法得到的窗导数就是这个深度可分卷积模型!)

4. MobileNetV1 网络结构

MobileNetV1 网络结构如下图所示,其中 Conv 表示普通卷积,Conv dw 表示 DW 卷积操作。在实验结果中, α \alpha α 控制使用卷积核的倍率, β \beta β 控制输入图像尺寸。当卷积核数量取 0.75 时,正确率降低了两个点,但是模型参数量核计算量少了近一半。同样的,减少输入尺寸从 224 到 192 时,计算量也有大幅降低,而正确率降低较少。我们可以基于自己的应用和资源设定 α \alpha α β \beta β 选择合适的模型。此时卷积的计算量变为 D k × D k × α × M × β × D F × β × D F + α × M × α × N × β × D F × β × D F D_k \times D_k \times \alpha \times M \times \beta \times D_F \times \beta \times D_F + \alpha \times M \times \alpha \times N \times \beta \times D_F \times \beta \times D_F Dk×Dk×α×M×β×DF×β×DF+α×M×α×N×β×DF×β×DF。按理说只有输出 N N N 才乘 α \alpha α 呀,DW 卷积保通道数,但是实际上输入 M M M 因为上一层的原因乘上了 α \alpha α

请添加图片描述

可以看到,MobileNetV1 有 95% 的计算量和 74.59% 的参数集中在 1 x 1 的卷积层上,而且几乎另外的参数也都在全连接层上。

请添加图片描述

具体 MobileNetV1 实验部分结果就不在赘述了。值得指出的是,很多人在使用时发现训练完之后,DW 卷积核很容易废掉,即卷积核参数大部分为 0。针对这个问题在 MobileNetV2 会有改善。

5. 代码

MobileNetV1 实现代码如下所示:

# 非官方实现

import torch
class MobileNet(nn.Module):
    def __init__(self):
        super(MobileNet, self).__init__()

        def conv_bn(inp, oup, stride):    # 第一层传统的卷积:conv3*3+BN+ReLU
            return nn.Sequential(
                nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
                nn.BatchNorm2d(oup),
                nn.ReLU(inplace=True)
            )

        def conv_dw(inp, oup, stride):      # 其它层的depthwise convolution:conv3*3+BN+ReLU+conv1*1+BN+ReLU
            return nn.Sequential(
                nn.Conv2d(inp, inp, 3, stride, 1, groups=inp, bias=False),
                nn.BatchNorm2d(inp),
                nn.ReLU(inplace=True),

                nn.Conv2d(inp, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
                nn.ReLU(inplace=True),
            )

        self.model = nn.Sequential(
            conv_bn(  3,  32, 2),   # 第一层传统的卷积
            conv_dw( 32,  64, 1),   # 其它层depthwise convolution
            conv_dw( 64, 128, 2),
            conv_dw(128, 128, 1),
            conv_dw(128, 256, 2),
            conv_dw(256, 256, 1),
            conv_dw(256, 512, 2),
            conv_dw(512, 512, 1),
            conv_dw(512, 512, 1),
            conv_dw(512, 512, 1),
            conv_dw(512, 512, 1),
            conv_dw(512, 512, 1),
            conv_dw(512, 1024, 2),
            conv_dw(1024, 1024, 1),
            nn.AvgPool2d(7),
        )
        self.fc = nn.Linear(1024, 1000)   # 全连接层

    def forward(self, x):
        x = self.model(x)
        x = x.view(-1, 1024)
        x = self.fc(x)
        return x
  • 9
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

木卯_THU

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值