1. 程式人生 > 其它 >深度學習中的 Attention 機制總結與程式碼實現(2017-2021年)

深度學習中的 Attention 機制總結與程式碼實現(2017-2021年)

作者丨mayiwei1998來源丨GiantPandaCV轉載自丨極市平臺

導讀

由於許多論文中的網路結構通常被嵌入到程式碼框架中,導致程式碼比較冗餘。本文作者對近幾年基於Attention網路的核心程式碼進行了整理和復現。

作者資訊:廈門大學計算機專業一年級研究生,歡迎大家關注Github:xmu-xiaoma666,知乎:努力努力再努力。

近幾年,Attention-based方法因其可解釋和有效性,受到了學術界和工業界的歡迎。但是,由於論文中提出的網路結構通常被嵌入到分類、檢測、分割等程式碼框架中,導致程式碼比較冗餘,對於像我這樣的小白很難找到網路的核心程式碼,導致在論文和網路思想的理解上會有一定困難。因此,我把最近看的Attention、MLP和Re-parameter論文的核心程式碼進行了整理和復現

,方便各位讀者理解。

本文主要對該專案的Attention部分做簡要介紹。專案會持續更新最新的論文工作,歡迎大家follow和star該工作,若專案在復現和整理過程中有任何問題,歡迎大家在issue中提出,我會及時回覆~

專案地址

https://github.com/xmu-xiaoma666/External-Attention-pytorch
(點選閱讀原文即可跳轉)

1. External Attention

1.1. 引用

Beyond Self-attention: External Attention using Two Linear Layers for Visual Tasks.---arXiv 2021.05.05

論文地址:https://arxiv.org/abs/2105.02358

1.2. 模型結構

1.3. 簡介

這是五月份在arXiv上的一篇文章,主要解決的Self-Attention(SA)的兩個痛點問題:(1)O(n^2)的計算複雜度;(2)SA是在同一個樣本上根據不同位置計算Attention,忽略了不同樣本之間的聯絡。因此,本文采用了兩個串聯的MLP結構作為memory units,使得計算複雜度降低到了O(n);此外,這兩個memory units是基於全部的訓練資料學習的,因此也隱式的考慮了不同樣本之間的聯絡。

1.4. 使用方法

from attention.ExternalAttention import ExternalAttention
import torch


input=torch.randn(50,49,512)
ea = ExternalAttention(d_model=512,S=8)
output=ea(input)
print(output.shape)

2. Self Attention

2.1. 引用

Attention Is All You Need---NeurIPS2017

論文地址:https://arxiv.org/abs/1706.03762

2.2. 模型結構

2.3. 簡介

這是Google在NeurIPS2017發表的一篇文章,在CV、NLP、多模態等各個領域都有很大的影響力,目前引用量已經2.2w+。Transformer中提出的Self-Attention是Attention的一種,用於計算特徵中不同位置之間的權重,從而達到更新特徵的效果。首先將input feature通過FC對映成Q、K、V三個特徵,然後將Q和K進行點乘的得到attention map,再將attention map與V做點乘得到加權後的特徵。最後通過FC進行特徵的對映,得到一個新的特徵。(關於Transformer和Self-Attention目前網上有許多非常好的講解,這裡就不做詳細的介紹了)

2.4. 使用方法

from attention.SelfAttention import ScaledDotProductAttention
import torch

input=torch.randn(50,49,512)
sa = ScaledDotProductAttention(d_model=512, d_k=512, d_v=512, h=8)
output=sa(input,input,input)
print(output.shape)

3. Squeeze-and-Excitation(SE) Attention

3.1. 引用

Squeeze-and-Excitation Networks---CVPR2018

論文地址:https://arxiv.org/abs/1709.01507

3.2. 模型結構

3.3. 簡介

這是CVPR2018的一篇文章,同樣非常具有影響力,目前引用量7k+。本文是做通道注意力的,因其簡單的結構和有效性,將通道注意力掀起了一波小高潮。大道至簡,這篇文章的思想可以說非常簡單,首先將spatial維度進行AdaptiveAvgPool,然後通過兩個FC學習到通道注意力,並用Sigmoid進行歸一化得到Channel Attention Map,最後將Channel Attention Map與原特徵相乘,就得到了加權後的特徵。

3.4. 使用方法

from attention.SEAttention import SEAttention
import torch

input=torch.randn(50,512,7,7)
se = SEAttention(channel=512,reduction=8)
output=se(input)
print(output.shape)

4. Selective Kernel(SK) Attention

4.1. 引用

Selective Kernel Networks---CVPR2019

論文地址:https://arxiv.org/pdf/1903.06586.pdf

4.2. 模型結構

4.3. 簡介

這是CVPR2019的一篇文章,致敬了SENet的思想。在傳統的CNN中每一個卷積層都是用相同大小的卷積核,限制了模型的表達能力;而Inception這種“更寬”的模型結構也驗證了,用多個不同的卷積核進行學習確實可以提升模型的表達能力。作者借鑑了SENet的思想,通過動態計算每個卷積核得到通道的權重,動態的將各個卷積核的結果進行融合。

個人認為,之所以所這篇文章也能夠稱之為lightweight,是因為對不同kernel的特徵進行通道注意力的時候是引數共享的(i.e. 因為在做Attention之前,首先將特徵進行了融合,所以不同卷積核的結果共享一個SE模組的引數)。

本文的方法分為三個部分:Split,Fuse,Select。Split就是一個multi-branch的操作,用不同的卷積核進行卷積得到不同的特徵;Fuse部分就是用SE的結構獲取通道注意力的矩陣(N個卷積核就可以得到N個注意力矩陣,這步操作對所有的特徵引數共享),這樣就可以得到不同kernel經過SE之後的特徵;Select操作就是將這幾個特徵進行相加。

4.4. 使用方法

from attention.SKAttention import SKAttention
import torch

input=torch.randn(50,512,7,7)
se = SKAttention(channel=512,reduction=8)
output=se(input)
print(output.shape)

5. CBAM Attention

5.1. 引用

CBAM: Convolutional Block Attention Module---ECCV2018

論文地址:https://openaccess.thecvf.com/content_ECCV_2018/papers/Sanghyun_Woo_Convolutional_Block_Attention_ECCV_2018_paper.pdf

5.2. 模型結構

5.3. 簡介

這是ECCV2018的一篇論文,這篇文章同時使用了Channel Attention和Spatial Attention,將兩者進行了串聯(文章也做了並聯和兩種串聯方式的消融實驗)。

Channel Attention方面,大致結構還是和SE相似,不過作者提出AvgPool和MaxPool有不同的表示效果,所以作者對原來的特徵在Spatial維度分別進行了AvgPool和MaxPool,然後用SE的結構提取channel attention,注意這裡是引數共享的,然後將兩個特徵相加後做歸一化,就得到了注意力矩陣。

Spatial Attention和Channel Attention類似,先在channel維度進行兩種pool後,將兩個特徵進行拼接,然後用7x7的卷積來提取Spatial Attention(之所以用7x7是因為提取的是空間注意力,所以用的卷積核必須足夠大)。然後做一次歸一化,就得到了空間的注意力矩陣。

5.4. 使用方法

from attention.CBAM import CBAMBlock
import torch

input=torch.randn(50,512,7,7)
kernel_size=input.shape[2]
cbam = CBAMBlock(channel=512,reduction=16,kernel_size=kernel_size)
output=cbam(input)
print(output.shape)

6. BAM Attention

6.1. 引用

BAM: Bottleneck Attention Module---BMCV2018

論文地址:https://arxiv.org/pdf/1807.06514.pdf

6.2. 模型結構

6.3. 簡介

這是CBAM同作者同時期的工作,工作與CBAM非常相似,也是雙重Attention,不同的是CBAM是將兩個attention的結果串聯;而BAM是直接將兩個attention矩陣進行相加。

Channel Attention方面,與SE的結構基本一樣。Spatial Attention方面,還是在通道維度進行pool,然後用了兩次3x3的空洞卷積,最後將用一次1x1的卷積得到Spatial Attention的矩陣。

最後Channel Attention和Spatial Attention矩陣進行相加(這裡用到了廣播機制),並進行歸一化,這樣一來,就得到了空間和通道結合的attention矩陣。

6.4.使用方法

from attention.BAM import BAMBlock
import torch

input=torch.randn(50,512,7,7)
bam = BAMBlock(channel=512,reduction=16,dia_val=2)
output=bam(input)
print(output.shape)

7. ECA Attention

7.1. 引用

ECA-Net: Efficient Channel Attention for Deep Convolutional Neural Networks---CVPR2020

論文地址:https://arxiv.org/pdf/1910.03151.pdf

7.2. 模型結構

7.3. 簡介

這是CVPR2020的一篇文章。

如上圖所示,SE實現通道注意力是使用兩個全連線層,而ECA是需要一個的卷積。作者這麼做的原因一方面是認為計算所有通道兩兩之間的注意力是沒有必要的,另一方面是用兩個全連線層確實引入了太多的引數和計算量。

因此作者進行了AvgPool之後,只是使用了一個感受野為k的一維卷積(相當於只計算與相鄰k個通道的注意力),這樣做就大大的減少的引數和計算量。(i.e.相當於SE是一個global的注意力,而ECA是一個local的注意力)。

7.4. 使用方法:

from attention.ECAAttention import ECAAttention
import torch

input=torch.randn(50,512,7,7)
eca = ECAAttention(kernel_size=3)
output=eca(input)
print(output.shape)

8. DANet Attention

8.1. 引用

Dual Attention Network for Scene Segmentation---CVPR2019

論文地址:https://arxiv.org/pdf/1809.02983.pdf

8.2. 模型結構

8.3. 簡介

這是CVPR2019的文章,思想上非常簡單,就是將self-attention用到場景分割的任務中,不同的是self-attention是關注每個position之間的注意力,而本文將self-attention做了一個拓展,還做了一個通道注意力的分支,操作上和self-attention一樣,不同的通道attention中把生成Q,K,V的三個Linear去掉了。最後將兩個attention之後的特徵進行element-wise sum。

8.4. 使用方法

from attention.DANet import DAModule
import torch

input=torch.randn(50,512,7,7)
danet=DAModule(d_model=512,kernel_size=3,H=7,W=7)
print(danet(input).shape)

9. Pyramid Split Attention(PSA)

9.1. 引用

EPSANet: An Efficient Pyramid Split Attention Block on Convolutional Neural Network---arXiv 2021.05.30

論文地址:https://arxiv.org/pdf/2105.14447.pdf

9.2. 模型結構

9.3. 簡介

這是深大5月30日在arXiv上上傳的一篇文章,本文的目的是如何獲取並探索不同尺度的空間資訊來豐富特徵空間。網路結構相對來說也比較簡單,主要分成四步,第一步,將原來的feature根據通道分成n組然後對不同的組進行不同尺度的卷積,得到新的特徵W1;第二步,用SE在原來的特徵上進行SE,從而獲得不同的阿頭疼託尼;第三步,對不同組進行SOFTMAX;第四步,將獲得attention與原來的特徵W1相乘。

9.4. 使用方法

from attention.PSA import PSA
import torch

input=torch.randn(50,512,7,7)
psa = PSA(channel=512,reduction=8)
output=psa(input)
print(output.shape)

10. Efficient Multi-Head Self-Attention(EMSA)

10.1. 引用

ResT: An Efficient Transformer for Visual Recognition---arXiv 2021.05.28

論文地址:https://arxiv.org/abs/2105.13677

10.2. 模型結構

10.3. 簡介

這是南大5月28日在arXiv上上傳的一篇文章。本文解決的主要是SA的兩個痛點問題:(1)Self-Attention的計算複雜度和n(n為空間維度的大小)呈平方關係;(2)每個head只有q,k,v的部分資訊,如果q,k,v的維度太小,那麼就會導致獲取不到連續的資訊,從而導致效能損失。這篇文章給出的思路也非常簡單,在SA中,在FC之前,用了一個卷積來降低了空間的維度,從而得到空間維度上更小的K和V。

10.4. 使用方法

from attention.EMSA import EMSA
import torch
from torch import nn
from torch.nn import functional as F

input=torch.randn(50,64,512)
emsa = EMSA(d_model=512, d_k=512, d_v=512, h=8,H=8,W=8,ratio=2,apply_transform=True)
output=emsa(input,input,input)
print(output.shape)

寫在最後

目前該專案整理的Attention的工作確實還不夠全面,後面隨著閱讀量的提高,會不斷對本專案進行完善,歡迎大家star支援。若在文章中有表述不恰、程式碼實現有誤的地方,歡迎大家指出~

CVPR和Transformer資料下載

後臺回覆:CVPR2021,即可下載CVPR 2021論文和程式碼開源的論文合集

後臺回覆:Transformer綜述,即可下載最新的兩篇Transformer綜述PDF

CVer-Transformer交流群成立

掃碼新增CVer助手,可申請加入CVer-Transformer微信交流群,方向已涵蓋:目標檢測、影象分割、目標跟蹤、人臉檢測&識別、OCR、姿態估計、超解析度、SLAM、醫療影像、Re-ID、GAN、NAS、深度估計、自動駕駛、強化學習、車道線檢測、模型剪枝&壓縮、去噪、去霧、去雨、風格遷移、遙感影象、行為識別、視訊理解、影象融合、影象檢索、論文投稿&交流、PyTorch和TensorFlow等群。

一定要備註:研究方向+地點+學校/公司+暱稱(如Transformer+上海+上交+卡卡),根據格式備註,可更快被通過且邀請進群