在网络中添加特征金字塔,和自注意力机制

这篇具有很好参考价值的文章主要介绍了在网络中添加特征金字塔,和自注意力机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

原网络结构

某"D网络"是用来进行睡眠微事件检测的深度学习模型。但是我发现该网络的性能并非十分完善;正如论文中所述的那样,在SSC、WSC睡眠数据集上对于纺锤波、K复合波等睡眠微事件的检测性能方面(包括precision、recall、F1-score)有待提高。
为此鄙人不才,希望能够改进该网络的结构,从而提高模型对睡眠微事件检测的性能。
下面是对该网络模型的简单描述。

1.空间滤波

空间滤波是由一个简单的二维卷积和转置操作组成的,这个做法通过使用卷积来对输入的信号进行线性的空间滤波操作,从而增加输入信号的信噪比。(但是我发现,在源码中真的只是用一个简单的卷积操作 ┭┮﹏┭┮)
真的很简单的卷积结构!!!

            nn.Conv2d(
                in_channels=1,
                out_channels=self.number_of_channels,
                kernel_size=(self.number_of_channels, 1),
                stride=1,
                padding=0)

2.特征提取

这个特征提取模块,也是我改进非常大的地方,因为我发现在作者提供的网络源代码中,只是用k个简单的卷积block组成(我想说仅仅通过卷积层、batchnorm、relu和maxpool真的能有好的性能么 ,ԾㅂԾ,)
这是该模块的大致结构,可以看见由k个包含二维卷积层的块组成。

nn.Sequential(
                    OrderedDict([
                        ("conv_{}".format(k), nn.Conv2d(
                            in_channels=4 * (2 ** (k - 1)) if k > 1 else 1,
                            out_channels=4 * (2 ** k),
                            kernel_size=(1, 3),
                            padding=(0, 1),
                            stride=1
                        )),
                        # ("cbam_{}".format(k),cbam(in_channel=4 * (2 ** k))),
                        ("batchnorm_{}".format(k), nn.BatchNorm2d(4 * (2 ** k))),
                        ("relu_{}".format(k), nn.ReLU()),
                        ("max_pooling_{}".format(k), nn.MaxPool2d(kernel_size=(1, 2),stride=(1,2))),
                    ])
                ) for k in range(1, self.k_max-1)

3.分类和定位

分类和定位模块也是通过卷积层实现的。【这里就不过多描述了 O(∩_∩)O】

改变特征提取模块中网络结构

这里只是简单的给网路进行改进,结合Yolov5当中FPN特征金字塔,并添加相应的CBAM注意力机制,希望能够使得网络的性能增强些。(目前新增结构正在训练验证中…)

1.使用ResNet-50网络加入FPN提取多尺度特征

特征金字塔设计的思路是因为,对于图像特征来说,底层具有较强的定位特征,而顶层具有较强的语义特征,那么就需要结合多尺度的特征来将高维和低维的特征进行融合。
在网络中添加特征金字塔,和自注意力机制
从上图FPN的结构中可以很好的进行观察,随着左半部分网络的加深,会使得语义信息更加得丰富。同时通过上采样的方法,不断放大特征图,能够使得低层特征也有丰富的语义信息。

在网络中添加特征金字塔,和自注意力机制
在上述结构当中,是将上采样的结果和自底向上生成的特征图进行融合。从左侧过来的特征图,需要先通过1x1的卷积进行通道的改变;然后和自顶向下而来的特征图进行add,之后还需要经过一个3x3的卷积(这里通过3x3的卷积是消除上采样产生的混叠效应,因为上采样和原图叠加后会造成特征的不连续,在原来特征图上失真,在灰度变化的地方可能出现明显的锯齿状

在这,我是在ResNet-50的网络中添加FPN(FPN结构的部分代码):

self.layer1 = nn.Sequential(*layers[:5])
        self.layer2 = nn.Sequential(*layers[5])
        self.layer3 = nn.Sequential(*layers[6])
        self.layer4 = nn.Sequential(*layers[7])
        # 使用1x1卷积进行侧向连接
        self.lateral5 = nn.Conv2d(in_channels=2048,out_channels=256,kernel_size=1)
        self.lateral4 = nn.Conv2d(in_channels=1024, out_channels=256, kernel_size=1)
        self.lateral3 = nn.Conv2d(in_channels=512, out_channels=256, kernel_size=1)
        self.lateral2 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=1)
        # 进行上采样
        self.upsample2 = nn.ConvTranspose2d(in_channels=256, out_channels=256, kernel_size=4, stride=2, padding=1)
        self.upsample3 = nn.ConvTranspose2d(in_channels=256, out_channels=256, kernel_size=4, stride=2, padding=1)
        self.upsample4 = nn.ConvTranspose2d(in_channels=256,out_channels=256, kernel_size=4, stride=2, padding=1)
        # 使用3x3的卷积,为了消除上采样产生的混叠效应
        self.smooth2 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1)
        self.smooth3 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1)
        self.smooth4 = nn.Conv2d(in_channels=256, out_channels=256, kernel_size=3, stride=1, padding=1)

然后将该模块加入到对应的网络当中。(ps:在这之前,需要将在该模块之前通过一个1x1的卷积层,用来改变通道数,从而能够符合该模块的输入通道。)

p2,p3,p4,p5 = self.fpn(self.conv1(x))

最终得到的p2,p3,p4,p5即为经过FPN后得到的多尺度特征图,接下来可以进行后续操作。

2.增加CBAM自注意力机制

在网络中添加注意力机制,可以提升网络的检测性能,在改进的网络中,我添加的是CBAM注意力机制。
CBAM注意力机制有两个模块,包括通道注意力机制和空间注意力机制。通过在通道和空间两个维度的分析,实现从通道到空间的注意力结构。
1.通道注意力机制
在网络中添加特征金字塔,和自注意力机制
以上图能够很好的将通道注意力机制的结构展现。通道注意力机制先将特征图进行全局最大池化和平均池化,从而获得两张不同维度的特征图(进行相应的转化:[b,c,h,w]==>[b,c,1,1],可以看到后面两个维度都变成1,可以看成在通道维的操作);然后通过一个公用的多层感知机网络,在这里需要使用1x1的卷积来改变通道数;将两个特征图在通道维度进行堆叠,最后通过激活函数进行权重归一化。
在这里展示通道注意力机制的部分代码:

class ChannelAttentionModule(nn.Module):
    def __init__(self, channel, ratio=4):
        super(ChannelAttentionModule, self).__init__()
        # 全局平均池化
        self.avg_pool = nn.AdaptiveAvgPool2d(1)
        # 全局最大池化
        self.max_pool = nn.AdaptiveMaxPool2d(1)
        # 公用的多层感知机网络
        self.shared_MLP = nn.Sequential(
            # 使用1x1卷积作为全连接层
            nn.Conv2d(channel, channel // ratio, 1, bias=False),
            nn.ReLU(),
            nn.Conv2d(channel // ratio, channel, 1, bias=False)
        )
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        avgout = self.shared_MLP(self.avg_pool(x))
        maxout = self.shared_MLP(self.max_pool(x))
        # 将两张图在通道维度进行堆叠
        return self.sigmoid(avgout + maxout)

2.空间注意力机制
在网络中添加特征金字塔,和自注意力机制
在这里,是要对之前通道注意力机制输出的特征图进行空间域方向的处理,可以看成将通道维度视为1,然后观察其他维。
首先需要对特征图进行最大池化和平均池化操作;然后将这两个特征图在通道维度进行concat;使用7x7或3x3(在这里我用的是7x7)的卷积融合通道信息;再经过激活函数对空间权重归一化。
空间注意力机制的代码如下所示:

# 空间注意力机制
class SpatialAttentionModule(nn.Module):
    def __init__(self):
        super(SpatialAttentionModule, self).__init__()
        self.conv2d = nn.Conv2d(in_channels=2, out_channels=1, kernel_size=7, stride=1, padding=3)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        # 平均池化
        avgout = torch.mean(x, dim=1, keepdim=True)
        # 最大池化
        maxout, _ = torch.max(x, dim=1, keepdim=True)
        # 将两张特征图在通道维度进行concat
        out = torch.cat([avgout, maxout], dim=1)
        out = self.sigmoid(self.conv2d(out))
        return out

ps:注意,以上需要将特征图和权重相乘,我都将此操作放到最后构造CBAM的forward()函数当中了 O(∩_∩)O

接下来就是将CBAM模块加入到改进后的网络中了,在这里我在网络最后的卷积后添加了CBAM模块,在这里为了保持原有网络结构的某些特征,我保留了原来DOSED网络中的两个卷积块,在这之后添加了CBAM。文章来源地址https://www.toymoban.com/news/detail-492826.html

到了这里,关于在网络中添加特征金字塔,和自注意力机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包