[注意力機制]CBAM:Convolutional Block Attention Module

論文鏈接: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介紹

中間特徵:F\epsilon R^{^{C\times H\times W}}

1Dchannel attention map:M_{c}\epsilon R^{^{C\times 1\times 1}}

2Dspatial attention map:M_{s}\epsilon R^{^{1\times H\times W}}

整個注意力過程:

\otimes表示點乘(element-wise multiplication) 

channel attention module

首先對於輸入特徵先進行平均尺化(average-pooling)和最大尺化(max-pooling )產生兩個兩個空間信息描述:Favg和Fmax。這兩個描述子進入共享網絡產生channel attention map:,這個共享網絡包括一個隱藏層的多層感知機。爲了減少參數,隱藏激活尺寸設定爲,這裏r就是減少率。然後通過元素求和合並兩個輸出。所以通道注意力計算:

查看代碼:W1和W0是兩個卷積層,同時W0後面還跟了一個relu激活,\sigma是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

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章