[ 轻量级网络 ] 经典网络模型2——MobileNet 详解与复现


🤵 AuthorHorizon John

编程技巧篇各种操作小结

🎇 机器视觉篇会变魔术 OpenCV

💥 深度学习篇简单入门 PyTorch

🏆 神经网络篇经典网络模型

💻 算法篇再忙也别忘了 LeetCode


🚀 MobileNet

MobileNet 使用 深度可分离卷积 来构建轻量级的深度神经网络,是一种用于 移动和嵌入式视觉 应用的高效模型 ;

通过引入的两个简单 全局超参数,有效地在 延迟和准确性 之间进行权衡 ;


🔗 论文地址:MobileNets: Efficient Convolutional Neural Networks for Mobile Vision Applications


在这里插入图片描述

MobileNet models can be applied to various recognition tasks for efficient on device intelligence

🚀 MobileNet 详解

🎨 MobileNet 网络结构

🚩 背景介绍

AlexNet于2012年获得 ImageNet Challenge(ILSVRC) 冠军以来,深度卷积神经网络在计算机视觉中得到了广泛的应用 ;
为使模型得到更高的精度,一般的趋势是使网络模型 加深、变复杂
但模型准确率的提高并不一定使网络在 规模和速度 方面更有效 ;
如在机器人自动驾驶汽车增强现实等许多现实应用中,识别任务需要在 计算能力有限的平台 上及时完成 ;

在这之前,人们构建小型模型主要通过两种方式:压缩与训练网络直接训练小型模型
但许多关于小型网络的论文只关注规模,而没有考虑速度 ;
MobileNet 主要专注于 优化延迟 ,但也产生小型网络 ;

因此,作者提出了一种 高效的网络体系结构和一组超参数
构建非常小、低延迟的模型 ,可以很容易地匹配移动和嵌入式视觉应用程序的设计需求 ;


🚩 Depthwise Separable Convolution

Depthwise Separable Convolution :深度可分离卷积

深度可分离卷积 分为两层:第一层 深度卷积(Depthwise Convolution)用于滤波,第二层 逐点卷积(Pointwise Convolution)用于合并,这样可以极大地减少 计算量模型大小


(a)标准卷积   (b)深度卷积   (c)逐点卷积

在这里插入图片描述

假设输入特征图为(DF × DF × M),卷积核大小为(Dk × Dk × N),M 和 N 分别为输入和输出通道数量 ;

则对应的 计算量 为:

  • 标准卷积 :DF × DF × M × DK × DK × N
  • 深度卷积 :DF × DF × M × DK × DK
  • 1×1点卷积 :DF × DF × M × N
  • 深度可分离卷积 :( DF × DF × M × DK × DK ) + ( DF × DF × M × N )

减少的计算量为:

( D F × D F × M × D K × D K ) + ( D F × D F × M × N ) D F × D F × M × D K × D K × N \frac {( D_F × D_F × M × D_K × D_K )+( D_F × D_F × M × N )} {D_F × D_F × M × D_K × D_K × N} DF×DF×M×DK×DK×NDF×DF×M×DK×DK+DF×DF×M×N = 1 N \frac {1} {N} N1 + 1 D K 2 \frac {1} {D^2_K} DK21

当使用 3×3 深度可分离卷积时,计算量可以减少 8-9 倍 ;


🚩 MobileNet 结构框图

MobileNet 结构建立在深度可分离卷积基础之上,在 深度卷积逐点卷积 之后加入归一化和激活层(BN and ReLU);

在这里插入图片描述

左:标准卷积   右:深度可分离卷积


在这里插入图片描述

从下表中可以看到:

模型将几乎所有的 计算 都放在密集的 1×1卷积 ;

(近95%的计算时间 和 近75%的模型参数)

在这里插入图片描述

训练模型过程中,与训练大型模型策略相反 :
使用较少的 正则化数据增强技术,这是由于小模型出现 过拟合 现象的可能性很低 ;


🚩 宽度倍增器

为构造更小且计算成本更低的模型,引入了一个非常简单的参数 α(宽度倍增器 ( Width Multiplier ) );

它可以在每一层均匀地细化网络,输入通道数 M 变为 αM,输出通道数 N 变为 αN

基于此得到的模型参数量为( α ∈ (0,1) ):

  • 深度可分离卷积 :( DF × DF × αM × DK × DK ) + ( DF × DF × αM × αN )

在这里插入图片描述

当 α = 0.25 时,结构变得太小,精度会平稳下降 ;


🚩 分辨率倍增器

降低神经网络计算代价的第二个超参数为 ρ (分辨率倍增器 ( Resolution Multiplier ) )

它可以减小输入特征图的尺寸,由 DF 变为 ρDF

基于以上两个超参数得到的模型参数量为( α ∈ (0,1) ,ρ ∈ (0,1] ):

  • 深度可分离卷积 :( ρDF × ρDF × αM × DK × DK ) + ( ρDF × ρDF × αM × αN )

在这里插入图片描述

上图为 ρ = 1,6/7,5/7,4/7 时分别对应的结果 ;


🚀 MobileNet 复现

# Here is the code :

import torch
import torch.nn as nn
from torchinfo import summary


def Depthwise_Separable(in_channels, out_channels, stride, padding):

    model = nn.Sequential(
        # 3 × 3 深度卷积
            nn.Conv2d(in_channels, in_channels, kernel_size=3, stride=stride, padding=padding, groups=in_channels, bias=False),
            nn.BatchNorm2d(in_channels),
            nn.ReLU6(inplace=True),
        # 1 × 1 点卷积
            nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=1, bias=False),
            nn.BatchNorm2d(out_channels),
            nn.ReLU6(inplace=True),
        )

    return model


class MobileNet(nn.Module):
    def __init__(self, num_classes=1000, width=1):
        super(MobileNet, self).__init__()

        self.first_conv = nn.Sequential(
            nn.Conv2d(in_channels=3, out_channels=32, kernel_size=3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(32),
            nn.ReLU6(inplace=True),
        )

        self.layers = nn.Sequential(
            Depthwise_Separable(width*32, width*64, 1, 1),
            Depthwise_Separable(width*64, width*128, 2, 1),
            Depthwise_Separable(width*128, width*128, 1, 1),
            Depthwise_Separable(width*128, width*256, 2, 1),
            Depthwise_Separable(width*256, width*256, 1, 1),
            Depthwise_Separable(width*256, width*512, 2, 1),
            Depthwise_Separable(width*512, width*512, 1, 1),
            Depthwise_Separable(width*512, width*512, 1, 1),
            Depthwise_Separable(width*512, width*512, 1, 1),
            Depthwise_Separable(width*512, width*512, 1, 1),
            Depthwise_Separable(width*512, width*512, 1, 1),
            Depthwise_Separable(width*512, width*1024, 2, 1),
            Depthwise_Separable(width*1024, width*1024, 2, 4),
        )

        self.pool = nn.AvgPool2d(kernel_size=7, stride=1)
        self.classifier = nn.Linear(width*1024, num_classes)
        self.softmax = nn.Softmax(dim=1)

    def forward(self, x):
        x = self.first_conv(x)
        x = self.layers(x)
        x = self.pool(x)
        x = torch.flatten(x, 1)
        x = self.classifier(x)
        out = self.softmax(x)
        return out


def test():
    net = MobileNet()
    y = net(torch.randn(1, 3, 224, 224))
    print(y.size())
    summary(net, (1, 3, 224, 224))


if __name__ == '__main__':
    test()

输出结果:

torch.Size([1, 1000])
==========================================================================================
Layer (type:depth-idx)                   Output Shape              Param #
==========================================================================================
MobileNet                                --                        --
├─Sequential: 1-1                        [1, 32, 112, 112]         --
│    └─Conv2d: 2-1                       [1, 32, 112, 112]         864
│    └─BatchNorm2d: 2-2                  [1, 32, 112, 112]         64
│    └─ReLU6: 2-3                        [1, 32, 112, 112]         --
├─Sequential: 1-2                        [1, 1024, 7, 7]           --
│    └─Sequential: 2-4                   [1, 64, 112, 112]         --
│    │    └─Conv2d: 3-1                  [1, 32, 112, 112]         288
│    │    └─BatchNorm2d: 3-2             [1, 32, 112, 112]         64
│    │    └─ReLU6: 3-3                   [1, 32, 112, 112]         --
│    │    └─Conv2d: 3-4                  [1, 64, 112, 112]         2,048
│    │    └─BatchNorm2d: 3-5             [1, 64, 112, 112]         128
│    │    └─ReLU6: 3-6                   [1, 64, 112, 112]         --
│    └─Sequential: 2-5                   [1, 128, 56, 56]          --
│    │    └─Conv2d: 3-7                  [1, 64, 56, 56]           576
│    │    └─BatchNorm2d: 3-8             [1, 64, 56, 56]           128
│    │    └─ReLU6: 3-9                   [1, 64, 56, 56]           --
│    │    └─Conv2d: 3-10                 [1, 128, 56, 56]          8,192
│    │    └─BatchNorm2d: 3-11            [1, 128, 56, 56]          256
│    │    └─ReLU6: 3-12                  [1, 128, 56, 56]          --
│    └─Sequential: 2-6                   [1, 128, 56, 56]          --
│    │    └─Conv2d: 3-13                 [1, 128, 56, 56]          1,152
│    │    └─BatchNorm2d: 3-14            [1, 128, 56, 56]          256
│    │    └─ReLU6: 3-15                  [1, 128, 56, 56]          --
│    │    └─Conv2d: 3-16                 [1, 128, 56, 56]          16,384
│    │    └─BatchNorm2d: 3-17            [1, 128, 56, 56]          256
│    │    └─ReLU6: 3-18                  [1, 128, 56, 56]          --
│    └─Sequential: 2-7                   [1, 256, 28, 28]          --
│    │    └─Conv2d: 3-19                 [1, 128, 28, 28]          1,152
│    │    └─BatchNorm2d: 3-20            [1, 128, 28, 28]          256
│    │    └─ReLU6: 3-21                  [1, 128, 28, 28]          --
│    │    └─Conv2d: 3-22                 [1, 256, 28, 28]          32,768
│    │    └─BatchNorm2d: 3-23            [1, 256, 28, 28]          512
│    │    └─ReLU6: 3-24                  [1, 256, 28, 28]          --
│    └─Sequential: 2-8                   [1, 256, 28, 28]          --
│    │    └─Conv2d: 3-25                 [1, 256, 28, 28]          2,304
│    │    └─BatchNorm2d: 3-26            [1, 256, 28, 28]          512
│    │    └─ReLU6: 3-27                  [1, 256, 28, 28]          --
│    │    └─Conv2d: 3-28                 [1, 256, 28, 28]          65,536
│    │    └─BatchNorm2d: 3-29            [1, 256, 28, 28]          512
│    │    └─ReLU6: 3-30                  [1, 256, 28, 28]          --
│    └─Sequential: 2-9                   [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-31                 [1, 256, 14, 14]          2,304
│    │    └─BatchNorm2d: 3-32            [1, 256, 14, 14]          512
│    │    └─ReLU6: 3-33                  [1, 256, 14, 14]          --
│    │    └─Conv2d: 3-34                 [1, 512, 14, 14]          131,072
│    │    └─BatchNorm2d: 3-35            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-36                  [1, 512, 14, 14]          --
│    └─Sequential: 2-10                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-37                 [1, 512, 14, 14]          4,608
│    │    └─BatchNorm2d: 3-38            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-39                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-40                 [1, 512, 14, 14]          262,144
│    │    └─BatchNorm2d: 3-41            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-42                  [1, 512, 14, 14]          --
│    └─Sequential: 2-11                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-43                 [1, 512, 14, 14]          4,608
│    │    └─BatchNorm2d: 3-44            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-45                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-46                 [1, 512, 14, 14]          262,144
│    │    └─BatchNorm2d: 3-47            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-48                  [1, 512, 14, 14]          --
│    └─Sequential: 2-12                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-49                 [1, 512, 14, 14]          4,608
│    │    └─BatchNorm2d: 3-50            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-51                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-52                 [1, 512, 14, 14]          262,144
│    │    └─BatchNorm2d: 3-53            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-54                  [1, 512, 14, 14]          --
│    └─Sequential: 2-13                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-55                 [1, 512, 14, 14]          4,608
│    │    └─BatchNorm2d: 3-56            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-57                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-58                 [1, 512, 14, 14]          262,144
│    │    └─BatchNorm2d: 3-59            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-60                  [1, 512, 14, 14]          --
│    └─Sequential: 2-14                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-61                 [1, 512, 14, 14]          4,608
│    │    └─BatchNorm2d: 3-62            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-63                  [1, 512, 14, 14]          --
│    │    └─Conv2d: 3-64                 [1, 512, 14, 14]          262,144
│    │    └─BatchNorm2d: 3-65            [1, 512, 14, 14]          1,024
│    │    └─ReLU6: 3-66                  [1, 512, 14, 14]          --
│    └─Sequential: 2-15                  [1, 1024, 7, 7]           --
│    │    └─Conv2d: 3-67                 [1, 512, 7, 7]            4,608
│    │    └─BatchNorm2d: 3-68            [1, 512, 7, 7]            1,024
│    │    └─ReLU6: 3-69                  [1, 512, 7, 7]            --
│    │    └─Conv2d: 3-70                 [1, 1024, 7, 7]           524,288
│    │    └─BatchNorm2d: 3-71            [1, 1024, 7, 7]           2,048
│    │    └─ReLU6: 3-72                  [1, 1024, 7, 7]           --
│    └─Sequential: 2-16                  [1, 1024, 7, 7]           --
│    │    └─Conv2d: 3-73                 [1, 1024, 7, 7]           9,216
│    │    └─BatchNorm2d: 3-74            [1, 1024, 7, 7]           2,048
│    │    └─ReLU6: 3-75                  [1, 1024, 7, 7]           --
│    │    └─Conv2d: 3-76                 [1, 1024, 7, 7]           1,048,576
│    │    └─BatchNorm2d: 3-77            [1, 1024, 7, 7]           2,048
│    │    └─ReLU6: 3-78                  [1, 1024, 7, 7]           --
├─AvgPool2d: 1-3                         [1, 1024, 1, 1]           --
├─Linear: 1-4                            [1, 1000]                 1,025,000
├─Softmax: 1-5                           [1, 1000]                 --
==========================================================================================
Total params: 4,231,976
Trainable params: 4,231,976
Non-trainable params: 0
Total mult-adds (M): 568.76
==========================================================================================
Input size (MB): 0.60
Forward/backward pass size (MB): 80.69
Params size (MB): 16.93
Estimated Total Size (MB): 98.22
==========================================================================================


  • 5
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Horizon John

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

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

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

打赏作者

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

抵扣说明:

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

余额充值