文章目录[隐藏]
原文:EPSANet: An Efficient Pyramid Split Attention Block on Convolutional Neural Network
代码链接:https://github.com/murufeng/EPSANet
前言:
论文在CenterNet基础上增加通道注意力,所以基于CenterNet代码进行了修改,由于CenterNet有三种主干网络(hourglass、ResNet、 DLA),此文针对的是基于ResNet骨干网络的Centernet。(插入的代码部分基于Pytorch)
核心:
基于CenterNet目标检测算法;引入通道注意力,并加入多尺度思想,提出金字塔分割注意力模块,PSA module;
论文的方法(默认已经对CenterNet有所了解):
建立PSA模块,主要包含以下4个步骤
1,利用SPC模块提取通道特征图上的多尺度特征
很多文献将此处提取过程翻译为切分为四个部分,这是不恰当的。对照源码(如下代码部分)可以看到这并不是一个切分的操作,而是对该特征图重复四次卷积,每次提取得到通道数为 原有通道数 / 4 的特征图,之后经过ConCat操作叠加回来(简单的堆叠)。
class PSAModule(nn.Module):
def __init__(self, inplans, planes, conv_kernels=[3, 5, 7, 9], stride=1, conv_groups=[1, 4, 8, 16]):
super(PSAModule, self).__init__()
self.conv_1 = conv(inplans, planes//4, kernel_size=conv_kernels[0], padding=conv_kernels[0]//2,
stride=stride, groups=conv_groups[0])
self.conv_2 = conv(inplans, planes//4, kernel_size=conv_kernels[1], padding=conv_kernels[1]//2,
stride=stride, groups=conv_groups[1])
self.conv_3 = conv(inplans, planes//4, kernel_size=conv_kernels[2], padding=conv_kernels[2]//2,
stride=stride, groups=conv_groups[2])
self.conv_4 = conv(inplans, planes//4, kernel_size=conv_kernels[3], padding=conv_kernels[3]//2,
stride=stride, groups=conv_groups[3])
self.se = SEWeightModule(planes // 4)
self.split_channel = planes // 4
self.softmax = nn.Softmax(dim=1)
def forward(self, x):
batch_size = x.shape[0]
x1 = self.conv_1(x)
x2 = self.conv_2(x)
x3 = self.conv_3(x)
x4 = self.conv_4(x)
feats = torch.cat((x1, x2, x3, x4), dim=1)
feats = feats.view(batch_size, 4, self.split_channel, feats.shape[2], feats.shape[3])
x1_se = self.se(x1)
x2_se = self.se(x2)
x3_se = self.se(x3)
x4_se = self.se(x4)
x_se = torch.cat((x1_se, x2_se, x3_se, x4_se), dim=1)
attention_vectors = x_se.view(batch_size, 4, self.split_channel, 1, 1)
attention_vectors = self.softmax(attention_vectors)
feats_weight = feats * attention_vectors
for i in range(4):
x_se_weight_fp = feats_weight[:, i, :, :]
if i == 0:
out = x_se_weight_fp
else:
out = torch.cat((x_se_weight_fp, out), 1)
return out
可以看到在forward中,对输入的x经过四次卷积得到x1,x2,x3,x4,卷积和的大小是分别指定的(源码为3,5,7,9),所以可以提取到不同尺度的特征图,并分别经过self.se操作(即SE注意力模块)。
真正的切分则存在于分组卷积中,正如原文所说,因为采用了不同的卷积核,所以导致参数量提高,所以使用分组卷积的方式,降低参数量。
2.提取不同尺度特征图的通道注意力
即通过SEWeight得到通道注意力向量,这点没什么好说的,具体可以参考注意力机制的相关文献,比较简单。
3.使用Softmax对输出的注意力向量重新标定,得到注意力权重
为什么使用softmax,以下是我的理解:如果看了SENet的应该知道,上一步注意力模块输出后的值是经过Sigmoid函数的输出,但我们需要的是通道间的权重,权重除了满足值为[0,1]还应当满足的条件就是所有权重相加的和为1,所以需要经过Softmax。
4.最后和单纯的SE模块相同,需要和源特征图想乘得到加权后的特征图。
梳理一下模块发生的流程:
整个PSA模块发生在ResNet框架中的残差块。替换了ResNet中的3×3卷积操作即
参考:https://blog.csdn.net/weixin_47196664/article/details/117857949
版权声明:本文为CSDN博主「MiracleHong」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/weixin_40671801/article/details/118380538
暂无评论