@toc
参考论文:CBAM: Convolutional Block Attention Module作者:Sanghyun Woo , Jongchan Park , Joon-Young Lee, In So Kweon;
1、简介
关键部分:提出了卷积块注意模块(CBAM),这是一种用于前馈卷积神经网络的简单而有效的注意模块。==给定一个中间特征图,我们的模块沿两个单独的维度(通道和空间)顺序推断注意力图,然后将注意力图乘以输入特征图以进行自适应特征细化。==因为 CBAM 是一个轻量级的通用模块,它可以无缝集成到任何 CNN 架构中,开销可以忽略不计,并且可以与基础 CNN 一起进行端到端训练。
关键词:目标检测,注意力机制,门控卷积。
2、CBAM概述
图 1:CBAM 概述。该模块有两个顺序子模块:通道和空间。中间特征图通过我们的模块(CBAM)在深度网络的每个卷积块上自适应地细化。
注意力不仅告诉你关注的地方,它还提高了兴趣的表现。我们的目标是通过使用注意力机制来增加表示能力:关注重要特征并抑制不必要的特征。在本文中,我们提出了一个新的网络模块,名为“卷积块注意模块”。由于卷积操作通过将跨通道和空间信息混合在一起来提取信息特征,我们采用我们的模块来强调沿着这两个主要维度的有意义的特征:通道和空间轴。为了实现这一点,我们依次应用通道和空间注意模块(如图 1 所示),以便每个分支可以分别学习通道和空间轴上的“什么”和“在哪里”。因此,我们的模块通过学习要强调或抑制哪些信息来有效地帮助网络内的信息流动。
该论文的三个主要贡献:
- 提出了一个简单而有效的注意力模块(CBAM),可以广泛应用于提高 CNN 的表示能力。
- 通过广泛的消融研究验证了注意力模块的有效性。
- 通过插入我们的轻量级模块,我们验证了各种网络的性能在多个基准测试(ImageNet-1K、MS COCO 和 VOC 2007)上得到了极大的改进。
3、Convolutional Block Attention Module
图 2:每个注意力子模块的示意图。如图所示,通道子模块利用共享网络同时使用最大池输出和平均池输出;空间子模块利用沿通道轴汇集的相似的两个输出并将它们转发到卷积层。
给定中间特征图 $F\in R^{C\times H \times W}$ 作为输入,CBAM 依次推断出 1D 通道注意力图 $M_c\in R^{C\times 1 \times 1}$ 和 2D 空间注意力图 $M_s\in R^{1\times H \times W}$,如图 1 所示。整个注意力过程可以概括为:
$$ F'=M_c(F)\otimes F,\\F''=M_s(F')\otimes F' $$
其中⊗表示逐元素乘法。在乘法过程中,注意力值被相应地广播(复制):通道注意力值沿空间维度广播,反之亦然。 F′′是最终的精炼输出。图 2 描述了每个注意力图的计算过程。下面描述每个注意力模块的细节。
3.1 Channel Attention Module(通道注意力模块)
我们首先通过使用平均池化和最大池化操作来聚合特征图的空间信息,生成两个不同的空间上下文描述符:$F_{avg}^{c}$和 $F_{max}^{c}$,分别表示平均池化特征和最大池化特征。然后将两个描述符转发到共享网络以生成我们的通道注意力图 $M_c\in R^{C\times 1\times 1}$。
==通道注意力机制的实现可以分为两个部分,我们会对输入进来的单个特征层,分别进行全局平均池化和全局最大池化。之后对平均池化和最大池化的结果,利用共享的全连接层进行处理,我们会对处理后的两个结果进行相加,然后取一个sigmoid,此时我们获得了输入特征层每一个通道的权值(0-1之间)。在获得这个权值后,我们将这个权值乘上原输入特征层即可。==
共享网络由具有一个隐藏层的多层感知器 (MLP) 组成。为了减少参数开销,隐藏激活大小设置为$R\in R^{C/r\times 1\times 1}$,其中 r 是缩减率。在将共享网络应用于每个描述符之后,我们使用逐元素求和来合并输出特征向量。简而言之,通道注意力被计算为:
$$ M_c(F)=\sigma (MLP(AvgPool(F))+MLP(MaxPool(F)))\\ =\sigma(W_1(W_0(F_{avg}^{c}))+W_1(W_0(F_{max}^{c}))) $$
其中 σ 表示 Sigmoid激活函数,$W_0\in R^{C/r \times C}$ , $W_1\in R^{C \times C/r}$ 。请注意,两个输入共享 MLP 权重 W0 和 W1,并且 ReLU 激活函数后面是 W0。
3.2 Spatial Attention Module(空间注意力模块)
==空间注意力机制,我们会对输入进来的特征层,在每一个特征点的通道上取最大值和平均值。之后将这两个结果进行一个堆叠,利用一次通道数为1的卷积调整通道数,然后取一个sigmoid,此时我们获得了输入特征层每一个特征点的权值(0-1之间)。在获得这个权值后,我们将这个权值乘上原输入特征层即可。==
我们利用特征的空间关系生成空间注意力图。与通道注意力不同,空间注意力集中在“哪里”是一个信息部分,这是对通道注意力的补充。为了计算空间注意力,我们首先沿通道轴应用平均池化和最大池化操作,并将它们连接起来以生成有效的特征描述符。沿通道轴应用池化操作被证明可以有效地突出信息区域[33]。在级联特征描述符上,我们应用卷积层来生成空间注意力图 $M_s(F) \in R^{H \times W}$,它编码了要强调或抑制的位置。我们将在下面描述详细的操作。
我们通过使用两个池化操作来聚合特征图的通道信息,生成两个 2D 图:$F_{avg}^{s}\in R^{1\times H\times W}$ 和 $F_{max}^{s}\in R^{1\times H\times W}$。每个表示通道中的平均池化特征和最大池化特征。然后将它们连接起来并通过标准卷积层进行卷积,生成我们的 2D 空间注意力图。简而言之,空间注意力被计算为:
$$ M_s(F)=\sigma (f^{7 \times 7}([AvgPool(F);MaxPool(F)]))\\ =\sigma(f^{7\times 7}([F_{avg}^{s};F_{max}^{s}])) $$
其中 σ 表示 sigmoid激活函数,$f^{7\times 7}$ 表示卷积核大小为 7×7 的卷积操作。
作者在论文中指出,通道注意力和空间注意力顺序方式放置比并行方式效果更好,且通道优先顺序略好于空间优先顺序
表 3:通道和空间注意力的结合方法。使用这两种注意力至关重要,而最佳组合策略(即顺序、通道优先)进一步提高了准确性。
4、相关实验
图 3:CBAM 与 ResNet[5] 中的 ResBlock 集成。该图显示了我们的模块在集成到 ResBlock 时的确切位置。我们在每个块的卷积输出上应用 CBAM。
4.1 不同注意力方法的比较
表 1:不同通道注意力方法的比较。我们观察到,使用我们提出的方法优于最近提出的挤压和激发方法 [28]。这里比较了通道注意力的 3 种变体:平均池化、最大池化和两种池化的联合使用。请注意,具有平均池化的通道注意模块与 SE [28] 模块相同。此外,当使用两个池时,我们使用共享的 MLP 进行注意力推理以保存参数,因为两个聚合通道特征都位于相同的语义嵌入空间中。我们在这个实验中只使用了通道注意模块,我们将缩减率固定为 16(即r=16)。
4.2 通道和空间注意力结合比较
表 3:通道和空间注意力的结合方法。使用这两种注意力至关重要,而最佳组合策略(即顺序、通道优先)进一步提高了准确性。通过实验发现发现采用更大的核大小在两种情况下都会产生更好的精度,所以使用卷积核大小为 7 的通道轴上的平均池化特征和最大池化特征作为我们的空间注意模块。
从结果中,我们可以发现顺序生成注意力图比并行生成更精细的注意力图。此外,通道优先级的性能略好于空间优先级。请注意,所有排列方法都优于单独使用通道注意力,这表明利用两种注意力至关重要,而最佳排列策略会进一步提高性能。
4.3 ImageNet-1K 上的图像分类
具有 CBAM 的网络显着优于所有baselines,表明 CBAM 可以很好地泛化大规模数据集中的各种模型
图 4:ImageNet-1K 训练期间的误差曲线。最好以彩色观看。
图 4 描绘了 ImageNet-1K 训练期间各种网络的误差曲线。我们可以清楚地看到,我们的方法在两个错误图中都表现出最低的训练和验证错误。它表明与 SE [28] 相比,CBAM 具有更大的能力来提高基线模型的泛化能力。
在表 4 中。CBAM 不仅显着提高了基线的准确性,而且还有利地提高了 SE [28] 的性能。这显示了 CBAM 在低端设备上应用的巨大潜力。
4.4 Grad-CAM网络可视化
图 5:Grad-CAM [18] 可视化结果。我们比较了 CBAM 集成网络(ResNet50 + CBAM)与基线(ResNet50)和 SE 集成网络(ResNet50 + SE)的可视化结果。为最后的卷积输出计算 grad-CAM 可视化。ground-truth标签显示在每个输入图像的顶部,P 表示ground-truth类的每个网络的 softmax 分数。
在图 5 中,我们可以清楚地看到 CBAM 集成网络的 Grad-CAM 掩码比其他方法更好地覆盖目标对象区域。也就是说,CBAM 集成网络能够很好地学习利用目标对象区域中的信息并从中聚合特征。
4.5 MC COCO目标检测
表 6:MS COCO 验证集上的对象检测 mAP(%)。我们采用 Faster R-CNN [41] 检测框架并将我们的模块应用于基础网络。 CBAM 将两个基线网络的 mAP@[.5, .95] 提高了 0.9。
4.6 VOC 2007目标检测
表 7:VOC 2007 测试集上的对象检测 mAP(%)。我们采用 StairNet [30] 检测框架,并将 SE 和 CBAM 应用于检测器。 CBAM 以可忽略的附加参数有利地改进了所有强基线。
5、Tensorflow复现CBAM
import tensorflow as tf
from tensorflow.keras.layers import Activation, Add, Concatenate, Conv1D, Conv2D, Dense,multiply,Input
from tensorflow.keras.layers import GlobalAveragePooling2D, GlobalMaxPooling2D, Lambda, BatchNormalization,Reshape
from tensorflow.keras.layers import Multiply
from tensorflow.keras.models import Model
from plot_model import plot_model
5.1 Channel Attention Module
# Channel Attention Module
# 原论文中r=16,但是我看github上面的r=8
def channelAttention(input_feature,ratio=16,name=""):
# 获取特征层的通道数
channel=input_feature.shape[-1]
shared_layer_one=Dense(channel//ratio,
activation='relu',
use_bias=False,
name="channel_attention_shared_one_" + str(name))
shared_layer_two=Dense(channel,
use_bias=False,
name="channel_attention_shared_two_" + str(name))
# 全局平均池化
avg_pool=GlobalAveragePooling2D()(input_feature)
# 全局最大池化
max_pool=GlobalMaxPooling2D()(input_feature)
avg_pool=Reshape((1,1,channel))(avg_pool)
max_pool=Reshape((1,1,channel))(max_pool)
avg_pool=shared_layer_one(avg_pool)
max_pool=shared_layer_one(max_pool)
avg_pool=shared_layer_two(avg_pool)
max_pool=shared_layer_two(max_pool)
#相加
cbam_feature=Add()([avg_pool,max_pool])
#获得输入特征层每一个通道的权值
cbam_feature=Activation('sigmoid')(cbam_feature)
#将这个权值与原输入特征层相乘
out=Multiply()([input_feature,cbam_feature])
return out
5.2 Spatial Attention Module
# Spatial Attention Module
def spatialAttention(input_feature,kernel_size=7,name=""):
cbam_feature=input_feature
#在通道维度上分别做最大池化和平均池化
avg_pool=tf.reduce_mean(input_feature,axis=3,keepdims=True)
max_pool=tf.reduce_max(input_feature,axis=3,keepdims=True)
concat=Concatenate(axis=3)([avg_pool,max_pool])
cbam_feature=Conv2D(filters=1,
kernel_size=kernel_size,
strides=1,
padding='same',
use_bias=False,
name="spatial_attention_" + str(name))(concat)
cbam_feature=Activation('sigmoid')(cbam_feature)
out=Multiply()([input_feature,cbam_feature])
return out
5.3 CBAM Block
# CBAM Block
def cbamBlock(cbam_feature,ratio=16,name=""):
# 先通道注意力,再空间注意力,原论文中真名这种排列效果更好。
cbam_feature=channelAttention(cbam_feature,ratio,name)
cbam_feature=spatialAttention(cbam_feature,name)
return cbam_feature
inputs=Input([26,26,512])
x=channelAttention(inputs)
x=spatialAttention(x)
model=Model(inputs,x)
model.summary()
这篇论文中主要是和SENet进行比较,但是我在我自己的数据集上面测试下来CBAM的表现还不如SENet和ECA-Net,可能跟我的数据集有关,这个就几千张图片,数据量太少了。
References
Woo S, Park J, Lee J Y, et al. Cbam: Convolutional block attention module[C]//Proceedings of the European conference on computer vision (ECCV). 2018: 3-19.
https://github.com/kobiso/CBAM-keras/blob/master/models/attention_module.py