MobileNetV3网络深入解析与Pytorch实现

Table of Contents

正文

网络结构优化

网络结构

MobileNetV3 block

MobileNetV3-Large

MobileNetV3-Small

MobileNetV3实现

block

MobileNetV3-Large

MobileNetV3-Small


论文名:Searching for MobileNetV3

论文地址:https://arxiv.org/pdf/1905.02244.pdf

正文

  MobileNetV3是Google继MobileNet V1,V2之后的又一个应用于移动端的轻量级网络,V3结合了V1的depthwise separable convolutions(详情移步MobileNetV1),V2的inverted residual with linear bottleneck(详情移步MobileNetV2)和SE结构(详情请移步SENet),并通过结合硬件感知网络架构搜索(NAS)和NetAdapt算法对网络结构进行了优化,性能优于前两个网络.

网络结构优化

  我对NAS和NetAdapt不了解,同时也感觉自动搜索得到的网络架构不属于人力范畴,我就只说明一下网络结构优化的点,方便大家在自己实现网络时参考.

  1.在之前的网络设计中,最后都会采用一个1*1卷积来提高输出特征图数量(960->1280),为了提速,V3将1*1卷积放在average pooling之后,如下图所示

         

  2.在初使结构中,通常输出的是32维通道(3->32),这里输出16维通道,并使用hswish替代relu

                 

  3.使用h-sigmoid(将h-swish表达式中的x去掉),用来替换SE结构中的sigmoid,并设定SE结构压缩系数为4

                                                     

网络结构

MobileNetV3 block

  MobileNetV3 block在MobileNetV2的基础上增加了SE结构,如下图所示

         

MobileNetV3-Large

          

MobileNetV3-Small

          

MobileNetV3实现

block

class hswish(nn.Module):
    def __init__(self):
        super().__init__()
        self.relu6 = nn.ReLU6(inplace=True)

    def forward(self, x):
        out = x*self.relu6(x+3)/6
        return out


class hsigmoid(nn.Module):
    def __init__(self):
        super().__init__()
        self.relu6 = nn.ReLU6(inplace=True)

    def forward(self, x):
        out = self.relu6(x+3)/6
        return out


class SE(nn.Module):
    def __init__(self, in_channels, reduce=4):
        super().__init__()

        self.se = nn.Sequential(
            nn.AdaptiveAvgPool2d(1),
            nn.Conv2d(in_channels, in_channels//reduce, 1, bias=False),
            nn.BatchNorm2d(in_channels//reduce),
            nn.ReLU6(inplace=True),
            nn.Conv2d(in_channels // reduce, in_channels, 1, bias=False),
            nn.BatchNorm2d(in_channels),
            hsigmoid()
        )

    def forward(self, x):
        out = self.se(x)
        out = x*out
        return out


class Block(nn.Module):
    def __init__(self, kernel_size, in_channels, expand_size, out_channels, stride, se=False, nolinear='RE'):
        super().__init__()

        self.se = nn.Sequential()
        if se:
            self.se = SE(expand_size)

        if nolinear == 'RE':
            self.nolinear = nn.ReLU6(inplace=True)
        elif nolinear == 'HS':
            self.nolinear = hswish()

        self.block = nn.Sequential(
            nn.Conv2d(in_channels, expand_size, 1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(expand_size),
            self.nolinear,

            nn.Conv2d(expand_size, expand_size, kernel_size, stride=stride,
                      padding=kernel_size // 2, groups=expand_size, bias=False),
            nn.BatchNorm2d(expand_size),
            self.se,
            self.nolinear,

            nn.Conv2d(expand_size, out_channels, 1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(out_channels)
        )

        self.shortcut = nn.Sequential()
        if stride == 1 and in_channels != out_channels:
            self.shortcut = nn.Sequential(
                nn.Conv2d(in_channels, out_channels, 1, bias=False),
                nn.BatchNorm2d(out_channels)
            )

        self.stride = stride

    def forward(self, x):
        out = self.block(x)

        if self.stride == 1:
            out += self.shortcut(x)

        return out

MobileNetV3-Large

class MobileNetV3_Large(nn.Module):
    def __init__(self, class_num=settings.CLASSES_NUM):
        super().__init__()

        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(16),
            hswish()
        )

        self.neck = nn.Sequential(
            Block(3, 16, 16, 16, 1),
            Block(3, 16, 64, 24, 2),
            Block(3, 24, 72, 24, 1),
            Block(5, 24, 72, 40, 2, se=True),
            Block(5, 40, 120, 40, 1, se=True),
            Block(5, 40, 120, 40, 1, se=True),
            Block(3, 40, 240, 80, 2, nolinear='HS'),
            Block(3, 80, 200, 80, 1, nolinear='HS'),
            Block(3, 80, 184, 80, 1, nolinear='HS'),
            Block(3, 80, 184, 80, 1, nolinear='HS'),
            Block(3, 80, 480, 112, 1, se=True, nolinear='HS'),
            Block(3, 112, 672, 112, 1, se=True, nolinear='HS'),
            Block(5, 112, 672, 160, 2, se=True, nolinear='HS'),
            Block(5, 160, 960, 160, 1, se=True, nolinear='HS'),
            Block(5, 160, 960, 160, 1, se=True, nolinear='HS'),
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(160, 960, 1, bias=False),
            nn.BatchNorm2d(960),
            hswish()
        )

        self.avgpool = nn.AdaptiveAvgPool2d(1)

        self.conv3 = nn.Sequential(
            nn.Conv2d(960, 1280, 1, bias=False),
            nn.BatchNorm2d(1280),
            hswish()
        )

        self.conv4 = nn.Conv2d(1280, class_num, 1, bias=False)

    def forward(self, x):
        x = self.conv1(x)
        x = self.neck(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = x.flatten(1)

        return x

MobileNetV3-Small

class MobileNetV3_Small(nn.Module):
    def __init__(self, class_num=settings.CLASSES_NUM):
        super().__init__()

        self.conv1 = nn.Sequential(
            nn.Conv2d(3, 16, 3, stride=2, padding=1, bias=False),
            nn.BatchNorm2d(16),
            hswish()
        )

        self.neck = nn.Sequential(
            Block(3, 16, 16, 16, 2, se=True),
            Block(3, 16, 72, 24, 2),
            Block(3, 24, 88, 24, 1),
            Block(5, 24, 96, 40, 2, se=True, nolinear='HS'),
            Block(5, 40, 240, 40, 1, se=True, nolinear='HS'),
            Block(5, 40, 240, 40, 1, se=True, nolinear='HS'),
            Block(5, 40, 120, 48, 1, se=True, nolinear='HS'),
            Block(5, 48, 144, 48, 1, se=True, nolinear='HS'),
            Block(5, 48, 288, 96, 2, se=True, nolinear='HS'),
            Block(5, 96, 576, 96, 1, se=True, nolinear='HS'),
            Block(5, 96, 576, 96, 1, se=True, nolinear='HS'),
        )

        self.conv2 = nn.Sequential(
            nn.Conv2d(96, 576, 1, bias=False),
            nn.BatchNorm2d(576),
            hswish()
        )

        self.avgpool = nn.AdaptiveAvgPool2d(1)

        self.conv3 = nn.Sequential(
            nn.Conv2d(576, 1280, 1, bias=False),
            nn.BatchNorm2d(1280),
            hswish()
        )

        self.conv4 = nn.Conv2d(1280, class_num, 1, bias=False)

    def forward(self, x):
        x = self.conv1(x)
        x = self.neck(x)
        x = self.conv2(x)
        x = self.conv3(x)
        x = self.conv4(x)
        x = x.flatten(1)

        return x

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
MobileNetV3是Google推出的第三代轻量化网络,用于在移动平台上进行神经网络的部署和应用。它在精度和计算量上都达到了新的水平。MobileNetV3的主要特点包括: 1. MobileNetV1:MobileNetV1通过将普通的卷积操作分解为深度卷积和点卷积两步来减少通道融合时间和参数。深度卷积是仅卷积不求和的操作,而点卷积是对深度卷积的多通道结果进行融合的1x1卷积。 2. MobileNetV2:MobileNetV2引入了反转残差块,先将通道数增加再减少,以解决在输入通道数较多时丢失信息的问题。这种结构可以减少神经元抑制导致的信息丢失。 3. MobileNetV3MobileNetV3重新设计了网络结构,并引入了H-Swish激活函数与ReLU搭配使用。此外,还引入了Squeeze-And-Excite模块,用于增强网络的表示能力。 关于MobileNetV3PyTorch实现,您可以参考作者团队的GitHub项目,链接为:https://github.com/yichaojie/MobileNetV3。该项目是根据论文描述的网络结构进行复现,并使用oxFlower17数据集进行了训练,确保了可行性。 如果您想了解更多关于MobileNetV3的详细信息,可以参考原文《Searching for MobileNetV3》。该论文由Google AI和Google Brain团队撰写,原文链接为:https://arxiv.org/abs/1905.02244v3。 #### 引用[.reference_title] - *1* *2* [pytorch实现并训练MobileNetV3](https://blog.csdn.net/baidu_38406307/article/details/107374989)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【MobileNetV3Pytorch实现(图像分类)](https://blog.csdn.net/weixin_43312117/article/details/121236450)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值