論文鏈接:https://arxiv.org/abs/1807.06521v2
代碼:https://github.com/luuuyi/CBAM.PyTorch
(最近在看人臉識別的輕量級網絡,然後看到了與cbam相關的內容,就想嘗試以下效果,是否有助於提升模型人臉識別的能力;)
論文的貢獻:作者提出了卷積層的注意力模塊(Convolutional Block Attention Module,CBAM),這個模塊分爲兩個部分:channel和spatial。通過與輸入特徵相乘,自適應的對特徵進行提純(refinement)。這種注意力模塊的優點就是:1,可以和任何CNN結構一起使用,不會增加額外的開銷,並且實現的是端對端的訓練。然後作者在分類(ImageNet-1K)和目標檢測數據集(MS COCO, VOC2007)上做實驗,效果都還很不錯。
作者提出的CBAM框圖:
通過作者提出的CBAM模塊,讓卷積網絡可以學習“what”和“where”是關注的焦點;
作者新想法的來源是兩篇參考文獻,文中是參考文獻【28】的channel-wise attention和參考文獻【29】spatial attention;
CBAM介紹:
中間特徵:
1Dchannel attention map:
2Dspatial attention map:
整個注意力過程:
表示點乘(element-wise multiplication)
channel attention module:
首先對於輸入特徵先進行平均尺化(average-pooling)和最大尺化(max-pooling )產生兩個兩個空間信息描述:Favg和Fmax。這兩個描述子進入共享網絡產生channel attention map:,這個共享網絡包括一個隱藏層的多層感知機。爲了減少參數,隱藏激活尺寸設定爲,這裏r就是減少率。然後通過元素求和合並兩個輸出。所以通道注意力計算:
查看代碼:W1和W0是兩個卷積層,同時W0後面還跟了一個relu激活,是sigmoid函數;
class ChannelAttention(nn.Module):
def __init__(self, in_planes, ratio=16):
super(ChannelAttention, self).__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.max_pool = nn.AdaptiveMaxPool2d(1)
self.fc1 = nn.Conv2d(in_planes, in_planes // 16, 1, bias=False)
self.relu1 = nn.ReLU()
self.fc2 = nn.Conv2d(in_planes // 16, in_planes, 1, bias=False)
self.sigmoid = nn.Sigmoid()
def forward(self, x):
avg_out = self.fc2(self.relu1(self.fc1(self.avg_pool(x))))
max_out = self.fc2(self.relu1(self.fc1(self.max_pool(x))))
out = avg_out + max_out
return self.sigmoid(out)
Spatial attention module:
對於特徵圖的channel information使用兩個尺化操作產生兩個2維的特徵,
然後經過concat後,進入卷積操作;
簡言之,spatial attention 計算:
代表是卷積核是7*7的卷積操作;
class SpatialAttention(nn.Module):
def __init__(self, kernel_size=7):
super(SpatialAttention, self).__init__()
assert kernel_size in (3, 7), 'kernel size must be 3 or 7'
padding = 3 if kernel_size == 7 else 1
self.conv1 = nn.Conv2d(2, 1, kernel_size, padding=padding, bias=False)
self.sigmoid = nn.Sigmoid()
self.tanh = nn.Tanh()
def forward(self, x):
avg_out = torch.mean(x, dim=1, keepdim=True)#每一行的均值;
max_out, _ = torch.max(x, dim=1, keepdim=True)#每一行的最大值;
x = torch.cat([avg_out, max_out], dim=1)
x = self.conv1(x)
return self.tanh(x) + 1
# return self.sigmoid(x) #ori
對於注意力機制模塊的安排:
1)按照串聯順序鏈接;
2)channel-first 會比spatial-first好;
實驗:
實驗部分,我很感興趣的是SE模塊和CBAM模塊的對比,結果是無論是分類還是目標檢測加入CBAM模塊的的結果完勝;
擴展閱讀:通道注意力SE模塊 https://blog.csdn.net/qq_22764813/article/details/95051082