MobileNetv3简记

MobileNetv3简记

  • 简单记录一下
MobileNetv2
  • 简单回顾下MobileNetv2,主要是引入了深度可分离卷积,见:MobileNetv2

-

MobileNetv3的主要修改
  • 1、看代码主要是加上了SqueezeExcitation模块(参考SENet)

  • 2、在网络末端减少1x1卷积(减少的这个是用来改变通道的),不过在我看来应该是作者试验了一下,发现减少了效果也还行,就说了 (此话不负责)

    -

  • 3、在网络开头,减少3x3卷积核的数量,并使用非线性激活函数减少损失

    • hard swish nonlinearity

      • image-20211207150223854
    • 由于sigmoid计算代价大,于是乎换成了ReLU6,效果似乎还可以

      • image-20211207150320665
      • image-20211207150326128
    • (We were able to reduce the number of filters to 16 either ReLU or swish(原本是32))

代码
# 这段是主体部分
class InvertedResidual(nn.Module):
    def __init__(self, cnf: InvertedResidualConfig,
                 norm_layer: Callable[..., nn.Module]):
        super(InvertedResidual, self).__init__()

        if cnf.stride not in [1, 2]:
            raise ValueError("illegal stride value.")

        self.use_res_connect = (cnf.stride == 1 and cnf.input_c == cnf.out_c)

        layers: List[nn.Module] = []
        activation_layer = nn.Hardswish if cnf.use_hs else nn.ReLU

        # expand
        if cnf.expanded_c != cnf.input_c:
            layers.append(
                ConvBNActivation(cnf.input_c,
                                 cnf.expanded_c,
                                 kernel_size=1,
                                 norm_layer=norm_layer,
                                 activation_layer=activation_layer))

        # depthwise
        layers.append(
            ConvBNActivation(cnf.expanded_c,
                             cnf.expanded_c,
                             kernel_size=cnf.kernel,
                             stride=cnf.stride,
                             groups=cnf.expanded_c,
                             norm_layer=norm_layer,
                             activation_layer=activation_layer))

        if cnf.use_se:
          	# 这里要用SE了
            layers.append(SqueezeExcitation(cnf.expanded_c))

        self.block = nn.Sequential(*layers)
        self.out_channels = cnf.out_c
        self.is_strided = cnf.stride > 1

    def forward(self, x: Tensor) -> Tensor:
        result = self.block(x)
        if self.use_res_connect:
            result += x
        return result

# SE的实现如下      
class SqueezeExcitation(nn.Module):
    def __init__(self, input_c: int, squeeze_factor: int = 4):
        super().__init__()
        # 这个结构其实就是加入了SENet的思想
        squeeze_c = _make_divisible(input_c // squeeze_factor, 8)
        self.fc1 = nn.Conv2d(in_channels=input_c,
                             out_channels=squeeze_c,
                             kernel_size=1)
        self.fc2 = nn.Conv2d(in_channels=squeeze_c,
                             out_channels=input_c,
                             kernel_size=1)

    def forward(self, x):
        scale = F.adaptive_avg_pool2d(x, output_size=(1, 1))
        scale = self.fc1(scale)
        scale = F.relu(scale, inplace=True)
        scale = self.fc2(scale)
        scale = F.hardsigmoid(scale, inplace=True)
        return scale * x
语义分割的应用
  • Lite R-ASPP,没试过,但是感觉Segmentation Head没有太大的创新
  • 在这里插入图片描述
总结
  • 看起来改动不大,主要就SE模块,网络末端减少1x1卷积,ReLU6三块内容,不知道有没有漏掉了~
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

椰子奶糖

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

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

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

打赏作者

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

抵扣说明:

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

余额充值