mmclassification backbone04-mobilenetV3

目录

前景概述

mobilenetV3论文

mobilenetV3网络结构(Large)

 网络结构逐层分析

 mmclassification实现V3


前景概述

(1)mobilenetV2;

(2)mobilenetV3主要贡献简单来说,有三点,一是SE-Net优化了InvertedResidual,二是使用NAS搜索出最优的网络结构,三是提出了新的激活函数h-swish.

mobilenetV3论文

https://arxiv.org/pdf/1905.02244.pdf

mobilenetV3网络结构(Large)

 网络结构逐层分析

第1层conv2d,结构是conv2d + bn + HSwish. 注意这里的激活函数是HSwish是公式是:

              

RE是指soft形式,即ReLU正常形式。其中HS实现如下。

class hswish(nn.Module):
    def forward(self, x):
        out = x * F.relu6(x + 3, inplace=True) / 6
        return out

第1层实现如下。

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

中间15层bneck

是mobilenetV3提出的新组件,相对于V2多了SE-Net插件。V2和V3组件对比。

 SE-Net插件,简单来说就是两步,squeeze操作和excitation操作,如下所示。

(1)先squeeze操作,用白话讲就是对前面的特征图U进行avgPooling,得到1x1xC的特征向量;(2)然后excitation操作,其实就是fc全连接,得到新的特征向量;

(3)最后用这个新的特征向量逐点卷积pw,即对U每个通道分别加权。

SE-Net插件代码

class SeModule(nn.Module):
    def __init__(self, in_size, reduction=4):
        super(SeModule, self).__init__()
        self.se = nn.Sequential(
            nn.AdaptiveAvgPool2d(1),  # 1x1xC
            
            # 这里用全卷积形式
            nn.Conv2d(in_size, in_size // reduction, kernel_size=1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(in_size // reduction),
            nn.ReLU(inplace=True),
            
            # 论文中的组件是有两个fc的
            nn.Conv2d(in_size // reduction, in_size, kernel_size=1, stride=1, padding=0, bias=False),
            nn.BatchNorm2d(in_size),
            hsigmoid()
        )

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

 bneck代码

class Block(nn.Module):
    """expand + depthwise + pointwise,
        eg:
        Block(3, 80, 184, 80, hswish(), None, 1),
        Block(3, 80, 480, 112, hswish(), SeModule(112), 1),
        """
    def __init__(self, kernel_size, in_size, expand_size, out_size, nolinear, semodule, stride):
        super(Block, self).__init__()
        self.stride = stride
        self.se = semodule  # SE-Net插件

        # pw, expand通道
        self.conv1 = nn.Conv2d(in_size, expand_size, kernel_size=1, stride=1, padding=0, bias=False)
        self.bn1 = nn.BatchNorm2d(expand_size)
        self.nolinear1 = nolinear

        # dw, 使用深度卷积,对每个通道分别单独卷积。实现形式是groups=input_channel。
        self.conv2 = nn.Conv2d(expand_size, expand_size, kernel_size=kernel_size, stride=stride, padding=kernel_size//2, groups=expand_size, bias=False)
        self.bn2 = nn.BatchNorm2d(expand_size)
        self.nolinear2 = nolinear

        # pw-linear,实现形式就是在pw基础上,去掉激活函数。
        self.conv3 = nn.Conv2d(expand_size, out_size, kernel_size=1, stride=1, padding=0, bias=False)
        self.bn3 = nn.BatchNorm2d(out_size)

        # 只有步长为1,且特征通道的情况下,才能使用跳层连接。
        self.shortcut = nn.Sequential()
        if stride == 1 and in_size != out_size:
            self.shortcut = nn.Sequential(  # 定义普通的1x1卷积。
                nn.Conv2d(in_size, out_size, kernel_size=1, stride=1, padding=0, bias=False),
                nn.BatchNorm2d(out_size),
            )

    def forward(self, x):
        out = self.nolinear1(self.bn1(self.conv1(x)))  # pw expand
        out = self.nolinear2(self.bn2(self.conv2(out)))  # dw
        out = self.bn3(self.conv3(out))  # pw-linear
        
        # se-net
        if self.se != None:
            out = self.se(out)

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

 mmclassification实现V3

作为backbone,去掉了bneck后面的所有4层。这里就不贴太多代码了,可参考V2讲解

    def forward(self, x):
        x = self.conv1(x)  # conv2d + bn + HS

        outs = []
        for i, layer_name in enumerate(self.layers):  # bneck层,记录每一层输出。
            layer = getattr(self, layer_name)
            x = layer(x)
            if i in self.out_indices:
                outs.append(x)

        if len(outs) == 1:  # 支持任意单层输出。
            return outs[0]
        else:
            return tuple(outs)  # 也支持多层输出。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr.Q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值