引言:
其实很早之前就知道这篇文章了,最近因为要用到多尺度融合的结构,所以就想到了这篇文章!在目标检测、语义分割以及其他的很多领域,目标尺度分步不均对于网络模型的处理能力要求就比较高,因此多尺度处理以及多尺度融合的策略就用的比较多。本文是提出一个多尺度的backbone网络,可以有效提升分类检测的性能!
创新点:
上图右边是标准的ResNet结构,右图为本文提出的Res2Net模块,将3x3卷积替换一个包含分组卷积和多尺度融合的模块。同时也可以搭配channel attention一起使用,即SE模块。
代码:
## Res2Net+SE
class R2CAB(nn.Module):
def __init__(self, channel, stride=1, scale=4, basewidth=28):
super(R2CAB, self).__init__()
width = int(math.floor(16 * (basewidth / 64.0)))
self.conv1 = nn.Conv2d(channel, width * scale, kernel_size=1, stride=stride, bias=True)
if scale == 1:
self.nums = 1
else:
self.nums = scale - 1
convs = []
for i in range(self.nums):
convs.append(nn.Conv2d(width, width, kernel_size=3, stride=stride, padding=1, bias=True))
self.convs = nn.ModuleList(convs)
self.conv3 = nn.Conv2d(width * scale, channel, kernel_size=1, stride=stride, bias=True)
self.relu = nn.ReLU(inplace=True)
self.scale = scale
self.width = width
# SELayer
self.ca = CALayer(channel)
def forward(self, x):
residual = x
# [N, width * scale, H, W]
out = self.relu(self.conv1(x))
# scale * [N, width , H, W]
spx = torch.split(out, self.width, 1)
for i in range(self.nums):
if i == 0:
sp = spx[i]
else:
sp = sp + spx[i]
sp = self.convs[i](sp)
sp = self.relu(sp)
if i == 0:
out = sp
else:
out = torch.cat((out, sp), 1)
out = torch.cat((out, spx[self.nums]), 1)
out = self.conv3(out)
out = self.ca(out)
out += residual
return out