赞
踩
目录
简要来说,注意力机制就是要让网络关注到它更需要关注的地方。
在卷积神经网络去处理图片的时候,我们会更希望卷积神经网络能从大量的信息中筛选出更重要的信息,而不是什么都关注,我们不可能手动去调节需要注意的地方,这个时候,如何让卷积神经网络去自适应的注意重要的物体变得极为重要。而注意力机制就是实现网络自适应注意的一个方式。
在神经网络中引入注意力机制的方法有很多种,以卷积神经网络为例,既可以在空间维度引入注意力机制,也可以在通道维度增加注意力机制(SENet),当然也有混合维度(CBAM),即在空间维度和通道维度都增加注意力机制。
总的来说,注意力机制可以分为通道注意力机制,空间注意力机制,以及二者的结合。
近年来,通道注意力机制被证明在提高深度卷积神经网络(cnn)性能方面具有巨大潜力。然而,大多数现有方法致力于开发更复杂的注意力模块以实现更好的性能,这不可避免地增加了模型的复杂性。为了克服性能和复杂性权衡的矛盾,提出了一种高效的通道注意力(ECA)模块,该模块仅涉及少量参数,同时带来明显的性能增益。通过剖析SENet中的通道注意力模块,经验表明,避免降维对学习通道注意力很重要,适当的跨通道交互可以在显著降低模型复杂度的同时性能。因此,本文提出了一种无需降维的局部跨通道交互策略,可以通过一维卷积高效实现。此外,提出了一种自适应选择一维卷积核大小的方法,确定局部跨通道交互的覆盖率。
关键点:避免降维,适当跨通道交互、自适应一维卷积核大小的算法
这里主要是对SENet通道注意力机制进行改进,去掉了全连接层,在全局平均池化后街上一个一维卷积层。
上图是使用RESNet作为骨干网络的注意力模块在分类精度、网络参数和FLOPs方面的比较。
横轴为网络参数量(百万)、纵轴为Top-1 准确率。
从图中可以看出ECA-Net具有较高的准确率,同时模型复杂度也更低。
具体实现:
给定输入特征,SE首先对每个通道独立的使用全局平均池化,然后使用两个具有非线性的全连接(FC)层,紧接着用一个Sigmoid函数来生成通道权重。两个FC层旨在捕获非线性跨通道交互,涉及到降维以控制模型复杂度。但实证研究表明,降维会给通道注意力预测带来副作用,并且捕获所有通道之间的依赖关系是低效且不必要的。
ECANet的作者认为降维会给通道注意力预测带来副作用,并且捕获所有通道之间的依赖关系是低效且不必要的。因此,提出了一种用于深度 CNN 的 Efficient Channel Attention (ECA) 模块,该模块避免了降维并以有效的方式捕获跨通道交互。如下图所示。
上图为高效通道注意力(ECA)模块示意图。给定通过全局平均池化(GAP)获得的聚合特征,ECA通过执行大小为 k 的快速1D卷积来生成通道权重,其中 k 通过通道维度 C 的映射自适应地确定。
和上面的SENet模块相比,ECANet在全局平均池化之后去除了全连接层,改用1*1卷积。
在没有降维的通道全局平均池化之后,ECANet使用一维卷积来实现跨通道信息交互,而卷积核的大小通过函数来自适应,内核大小 k 表示局部跨通道交互的覆盖范围,即有多少邻居参与了一个通道的注意力预测。这种方法被证明可以保证效率和有效性。
给定通道维度 C,卷积核大小 k 可以自适应地确定为:
其中 表示最接近 t 的奇数。在本文中,我们在所有实验中设置 和 = 1.
显然,通过映射 ψ,高维通道具有更长范围的相互作用,而低维通道通过使用非线性映射进行更短范围的相互作用。
- import torch
- from torch import nn
-
-
- class senet(nn.Module):
- def __init__(self, channel, ratio = 16):
- super(senet, self).__init__()
- self.avg_pool = nn.AdaptiveAvgPool2d(1)
- self.fc = nn.Sequential(
- nn.Linear(channel, channel // ratio, False),
- nn.ReLU(),
- nn.Linear(channel // ratio, channel, False),
- nn.Sigmoid()
- )
-
- def forward(self, x):
- b, c, h, w = x.size()
- # b, c, h, w -> b, c, 1, 1
- avg = self.avg_pool(x).view([b, c])
- fc = self.fc(avg)
-
- # b, c -> b, c //ratio -> b, c -> b, c, 1, 1
- fc =self.fc(avg).view([b, c, 1, 1])
-
- return x * fc
-
- model = senet(512)
- print(model)
- inputs = torch.ones([2, 512, 26, 26])
- outputs = model(inputs)
- import torch
- from torch import nn
- import math
-
- class eca_block(nn.Module):
- def __init__(self, channel, gamma=2, b=1):
- super(eca_block, self).__init__()
- kernel_size = int(abs((math.log(channel, 2) + b) / gamma))
- kernel_size = kernel_size if kernel_size % 2 else kernel_size + 1
- padding = kernel_size // 2
-
- self.avg_pool = nn.AdaptiveAvgPool2d(1)
- self.conv = nn.Conv1d(1, 1, kernel_size, padding=padding, bias=False)
- self.sigmoid = nn.Sigmoid()
-
- def forward(self, x):
- b, c, h, w = x.size()
-
- avg = self.avg_pool(x).view([b, 1, c])
- out = self.conv(avg)
- out = self.sigmoid(out).view([b, c, 1, 1])
- return out * x
-
- model = eca_block(512)
- print(model)
- inputs = torch.ones([2, 512, 26, 26])
- outputs = model(inputs)
参考论文:https://ieeexplore.ieee.org/document/9156697
作者:Qilong Wang; Banggu Wu; Pengfei Zhu; Peihua Li; Wangmeng Zuo; Qinghua Hu
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。