Res2Net

Res2Net: A New Multi-scale Backbone Architecture

Res2Net_第1张图片

 Res2Net_第2张图片

 Res2Net_第3张图片

原理介绍 

        我们知道两个3×3卷积等价于1个5×5卷积,3个3×3卷积等价于1个7×7卷积。卷积神经网络随着depth的增加,感受野也在增加,其本身就有学习multi scale的能力。本文的创新点在于提出了一个结构,增强了网络学习multi scale特征的能力,使其在一个更 granular(颗粒)的level来表示multi scale特征。

        对于一个通道数为c的input feature map,我们需要一个通道数同样为c的卷积核去学习其特征,在网络的某一层,我们有n个这样的卷积核,这一层的输出通道数就是n。作者在width、depth、cardinality之外提出一个新的dimension,scale。将输入特征图沿channel方向等分为scale份,如图2右边所示,对其中的一份进行3×3的卷积,输出一方面concatenate到输出中,一方面和下一份进行add,然后再进行3×3卷积,依次这样操作,最终输出再接1×1卷积得到这个block的输出。

        因为层与层之间卷积的堆叠以及下采样的操作,我们可以在不同层之间学习不同scale的特征。现在我们在同一层中就可以学习到不同scale的特征,大大增强了网络multi scale representation ability。

代码实现 

    def forward(self, x):
        """Forward function."""

        def _inner_forward(x):
            identity = x

            out = self.conv1(x)
            out = self.norm1(out)
            out = self.relu(out)

            spx = torch.split(out, self.width, 1)
            sp = self.convs[0](spx[0].contiguous())
            sp = self.relu(self.bns[0](sp))
            out = sp
            for i in range(1, self.scales - 1):
                if self.stage_type == 'stage':
                    sp = spx[i]
                else:
                    sp = sp + spx[i]
                sp = self.convs[i](sp.contiguous())
                sp = self.relu(self.bns[i](sp))
                out = torch.cat((out, sp), 1)

            if self.stage_type == 'normal' and self.scales != 1:
                out = torch.cat((out, spx[self.scales - 1]), 1)
            elif self.stage_type == 'stage' and self.scales != 1:
                out = torch.cat((out, self.pool(spx[self.scales - 1])), 1)

            out = self.conv3(out)
            out = self.norm3(out)

            if self.downsample is not None:
                identity = self.downsample(x)

            out += identity

            return out

        if self.with_cp and x.requires_grad:
            out = cp.checkpoint(_inner_forward, x)
        else:
            out = _inner_forward(x)

        out = self.relu(out)

        return out

其中需要注意

  1. 如Fig. 2 所示,原论文中split后x1不经过卷积,直接作为输出的y1,论文中也提到“To reduce the number of parameters, we omit the convolution for the first split, which can also be regarded as a form of feature reuse.” 但在mmlcs的实现中,是last split不经过卷积,直接concatenate到输出后面。
  2. 和resnet一样,res2net中在是在每个stage的第一个block中的第二个3×3卷积stride=2来实现downsample。如上面代码中所示,每个stage的第一个block的self.stage_type='stage',此时因为每个split经过3×3-s2的conv后spatial size变了就不能和下一个split进行add了。

你可能感兴趣的:(Classification,深度学习,计算机视觉,人工智能)