mmclassification backbone03-mobilenetV2

目录

前景概述

mobilenetV2论文

mobilenetV2网络结构:

网络结构逐层分析


前景概述

(1)mobilenetV1主要的贡献简单来说,就是提出了深度可分离卷积,即将普通卷积操作,拆分成两步,深度卷积depthConv (卷积核通道数时1)和逐点卷积(卷积核大小是1x1),即先空间卷积,再通道卷积。作用是显著降低计算复杂度。

(2)mobilenetV2主要贡献简单来说,就是结合了残差,提出了InvertedResidual层(正经的残差层是沙漏型的,这个是梭型的),提高了精度。

mobilenetV2论文

https://arxiv.org/pdf/1801.04381.pdf

mobilenetV2网络结构:

网络结构逐层分析

第1层是普通的conv2d+bn+relu6. mmclassification实现层层封装,不好看,这里贴简单实现

ef conv_bn(inp, oup, stride):
    return nn.Sequential(
        nn.Conv2d(inp, oup, 3, stride, 1, bias=False),
        nn.BatchNorm2d(oup),
        nn.ReLU6(inplace=True)
    )

 后面7层是bottleneck层。其中一个bottleneck实现

class InvertedResidual(nn.Module):
    def __init__(self, inp, oup, stride, expand_ratio):
        # inp, oup分别是输入和输出通道数。expand_ratio是通道放大倍数,用于中间隐藏层。
        super(InvertedResidual, self).__init__()
        self.stride = stride
        assert stride in [1, 2]

        hidden_dim = int(inp * expand_ratio)  # 内部的隐藏层通道都是这个数。
        # 只有步长为1且输入和输出通道数一样,才使用残差层,即有shortcut.
        # 即残差层不会改变特征图大小和通道数。
        self.use_res_connect = self.stride == 1 and inp == oup

        if expand_ratio == 1:  # dw -> pw_linear
            self.conv = nn.Sequential( 
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),  # ksize=3, padding=1, 注意group=input_channel,即输入的各个通道分别为一组
                nn.BatchNorm2d(hidden_dim),
                nn.ReLU6(inplace=True),
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),
                nn.BatchNorm2d(oup),
            )
        else:                # pw -> dw -> pw-linear.
            self.conv = nn.Sequential(
                # pw
                nn.Conv2d(inp, hidden_dim, 1, 1, 0, bias=False),  # 先用1x1卷积即pw,放大通道。
                nn.BatchNorm2d(hidden_dim),
                nn.ReLU6(inplace=True),
                # dw
                nn.Conv2d(hidden_dim, hidden_dim, 3, stride, 1, groups=hidden_dim, bias=False),  
                nn.BatchNorm2d(hidden_dim),
                nn.ReLU6(inplace=True),
                # pw-linear
                nn.Conv2d(hidden_dim, oup, 1, 1, 0, bias=False),  # 再用1x1线性卷积,缩小通道。
                nn.BatchNorm2d(oup),
            )

    def forward(self, x):
        if self.use_res_connect:
            return x + self.conv(x)
        else:
            return self.conv(x)

(1)上面的pw是论中的逐点卷积pointwise Conv,即1x1的卷积;

(2)dw是深度卷积depthwise Conv,即卷积核的通道数是1,计算时是与输入逐通道卷积。

(3)pw_linear是论文中的linear bottleneck,其实就是pw 1x1的卷积后,不用激活函数(非线性),mmclassification也是如此实现。

注意:这个反转残差InvertedResidual结构有多种。

(1)使用隐藏层通道数扩张倍率expand_ratio控制,即是否先用pw,即dw -> pw_linear 或者是pw -> dw -> pw-linear;

(2)只有步长为1且输入和输出通道数一样,才使用残差层,即有shortcut,如下所示,注意输入在底部。当repeated n times,只有第一个往往步长是2,用作下采样,其他必须是1,即后面都是不改变特征图大小和通道数的残差层。这样7层bottlenect每一层都只可能下采样一次。

 调用上面的InvertedResidual,实现7层bottleneck.

# building inverted residual blocks
for t, c, n, s in interverted_residual_setting:
	output_channel = make_divisible(c * width_mult) if t > 1 else c  # 重复t>1次,则通道需先乘以放大倍数,且能被8整除。
	for i in range(n):
		if i == 0:
			self.features.append(block(input_channel, output_channel, s, expand_ratio=t))
		else:
			self.features.append(block(input_channel, output_channel, 1, expand_ratio=t))
		input_channel = output_channel  # 重复多次时,内部隐藏层通道是固定的

在后面3层,分别是conv2d 1x1卷积(conv2d1x1+bn+relu6)、avgpooling、conv2d 1x1卷积分类输出层。

如果mmclassification,用作backbone时,去掉了后面两层。且支持多层输出,输出层可以时bottleneck7层和最后conv2d1x1中的任何一层或者多层。mmclassification代码如下所示。

def forward(self, x):
	x = self.conv1(x)  # 第一个普通卷积。输出层,不是从这里算起。

	outs = []  # 输出层从第一个bottleNeck算起,一共有7个,还有1个conv1x1. 0, 1, 2, 3, 4, 5, 6, 7. 7对应的是conv1x1.
	for i, layer_name in enumerate(self.layers):
		layer = getattr(self, layer_name)
		x = layer(x)  # 依次通过每一层。
		if i in self.out_indices:  # 记录需要输出的层。out_indices: (None or Sequence[int])
			outs.append(x)

	if len(outs) == 1:
		return outs[0]
	else:
		return tuple(outs)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

Mr.Q

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

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

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

打赏作者

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

抵扣说明:

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

余额充值