CNN與Transformer的強強聯(lián)合!谷歌最新開源BoTNet,ImageNet達84.7%準確率

極市導讀
?Conv+Transformer=BotNet,這是伯克利、谷歌最新提出的工作BotNet,它充分利用了CNN與自注意力的優(yōu)勢,在ImageNet上取得了84.7%的top1精度,同時文中各種實驗分析也相當?shù)脑敿殹?>>加入極市CV技術交流群,走在計算機視覺的最前沿

本文是伯克利與谷歌的研究在Convolution+Transformer組合方面一個探索,它采用混合方式同時利用了CNN的特征提取能力、transformer的內容自注意力與位置自注意力機制,取得了優(yōu)于純CNN(如ResNet、EfficientNet)或者自注意力(如ViT、DeiT)的性能。所提方案在ImageNet上取得了84.7%的top1精度;在COCO數(shù)據(jù)集上,基于MaskR-CNN取得了44.4%的MaskAP與49.7%的BoxAP指標。本文值得對Transformer感興趣的同學深入研究一番,文中各種實驗分析相當?shù)脑敿殹?/p>
Abstract
本文提出了一種概念簡單但強有力的骨干網(wǎng)絡BoTNet,它集成了自注意力機制并用于多個計算機視覺任務(包含圖像分類、目標檢測、實例分割)。通過簡單的采用全局自注意力模塊替換ResNet的最后三個Bottleneck模塊中的卷積,而無需其他改動即可得到BoTNet,相比baseline,所提方法可以在目標檢測與實例分割任務上取得顯著的性能提升,同時還可以降低參數(shù)量,代價為少量的推理延遲。
通過BoTNet的設計,本文同時指出:帶自注意力模塊的Bottleneck模塊可以視作Transformer模塊。無需任何技巧,基于Mask R-CNNN框架,BoTNet在COCO實例分割任務上取得了44.4%的Mask AP與49.7%的Box AP指標,超越了之前由ResNeSt的最佳指標。最后,本文還針對圖像分類任務進行了BoTNet的自適應設計,在ImageNet數(shù)據(jù)集上取得了84.7%的top1精度,同時比EfficientNe快2.33倍(硬件平臺為TPU-v3)。
Method
本文的的思路非常簡單:采用多頭注意力(Multi-Head Self Attention, MHSA)模塊替換Bottleneck中的卷積。而MHSA的結構示意圖見下圖。

一般來說,ResNet包含4個階段,即[c2, c3, c4, c5],它們分別對應stride=[4,8,16,32]尺寸的特征。[c2,c3,c4,c5]分別由多個Bottleneck模塊構成,比如ResNet50中的數(shù)量分別為[3,4,6,3]。ResNet50與BoTNet50的結構信息對比見下表。

本文與現(xiàn)有自注意力機制方法的一個區(qū)別在于:以Vit、SAN等為代表的自注意力機制參與到ResNet的各個階段的Bottleneck中取了;而BoTNet則只是參與到c5階段的Bottleneck。為什么會這種設計呢?原因分析如下:
本文的目的是采用注意力提升實例分割模型的性能,而實例分割模塊的輸入通常比較大(比如)。考慮到自注意力機制的計算量與內存占用問題,本文采用了上述最簡單的配置方式:即旨在最小分辨率特征c5階段添加自注意力模塊。而c5部分只包含3個Bottleneck,每個Bottleneck包含一個卷積,采用MHSA替換該卷積即可得到本文所涉及的BoTNet。而c5的第一個Bottleneck中的卷積stride=2,而MHSA模塊并不支持stride操作,故而本文詞用均值池化進行下采樣。而Stride=2版本的BoT模塊則如下圖所示。

為更好的使得注意力機制存在位置相關性,基于Transformer的架構引入了Position Encoding。而之前趙恒爽、賈佳亞等人提出的SAN方案已經(jīng)證實了位置編碼在視覺任務中的有效性,故而本文所設計的BoT模塊中同樣引入了與位置相關的自注意力機制。
最后,我們附上不同配置的網(wǎng)絡架構示意圖,見下圖。

Experiments
為更好的說明所提方案的有效性,我們在實例分割、目標檢測等任務上對其進行了論證。

我們先來看一下COCO實例分割上的效果,結果見上表。從上表可以看到:在12epoch訓練周期下,相比ResNet50,BoTNet50取得了有效的性能提升;而更長周期的訓練可以得到更為顯著的性能改善。

與此同時,為說明位置編碼的重要性,本文對其進行了消融實驗分析,結果見上表??梢钥吹剑?strong style="font-weight: bold;color: black;">內容注意力機制可以取得0.6AP性能提升,而位置注意力機制可以取得1.0AP性能提升;而兩者的組合則可以取得1.5AP性能提升。這說明內容與位置注意力具有互補性。

此外,本文還針對“為什么要替換c5中所有Bottleneck的卷積?”的問題進行消融實驗分析,結果見上表。很明顯,全部替換帶來的性能提升更大,且推理延遲代價很小。通過對比BoT50與BoT101還得出:自注意力機制的替換比堆疊卷積更有效。

在上述基礎上,作者還引入了多尺度jitter配置,可以看到BoT50還可以進一步的加劇性能提升。

另外,作者還將所提方法與非局部注意力機制進行了對比,結果見上表??梢钥吹剑?strong style="font-weight: bold;color: black;">BoT模塊帶來的性能提升要比NL模塊的提升更大;此外還可以看到:同時替換c4與c5還可以取得進一步的性能提升。

最后,我們再來看一下在圖像分類任務上所提方法與其他方案(包含SENet、EfficientNet、ViT、DeiT)的性能對比,結果見上表與下表??梢钥吹剑築oTNet取得了比DeiT-384更好的結果,這說明:混合模型可以同時利用卷積與自注意力的特性,取得優(yōu)于純注意力模型的效果。

全文到此結束,更多消融實驗分析建議查看原文,強烈建議感興趣的同學去研讀一下原文。
Code
另外吐槽一點:本文尚未提供預訓練模型,不過提供了Tensorflow和Pytorch實現(xiàn)(Pytorch為第三方)。這里提供一下核心的code,實現(xiàn)如下。
def MHSA(featuremap, pos_enc_type='relative', use_pos=True):q = group_pointwise(featuremap, proj_factor=1, name='q_proj', heads=heads,target_dimension=bottleneck_dimension)k = group_pointwise(featuremap, proj_factor=1, name='k_proj', heads=heads,target_dimension=bottleneck_dimension)v = group_pointwise(featuremap, proj_factor=1, name='v_proj', heads=heads,target_dimension=bottleneck_dimension)assert pos_enc_type in ['relative', 'absolute']o = relpos_self_attention(q=q, k=k, v=v, relative=use_pos, fold_heads=True)return odef group_pointwise(featuremap, proj_factor=1, name='grouppoint',heads=4, target_dimension=None):"""1x1 conv with heads."""with tf.variable_scope(name, reuse=tf.AUTO_REUSE):in_channels = featuremap.shape[-1]if target_dimension is not None:proj_channels = target_dimension // proj_factorelse:proj_channels = in_channels // proj_factorw = tf.get_variable('w',[in_channels, heads, proj_channels // heads],dtype=featuremap.dtype,initializer=tf.random_normal_initializer(stddev=0.01))out = tf.einsum('bHWD,Dhd->bhHWd', featuremap, w)return outdef relative_logits(q):"""Compute relative position enc logits."""with tf.variable_scope('relative', reuse=tf.AUTO_REUSE):bs, heads, h, w, dim = q.shapeint_dim = dim.value# Note: below, we passed stddev arg as mean for the initializer.# Providing code as is, with this small error.# right way: normal_initializer(stddev=int_dim**-0.5)# Relative logits in width dimension.rel_emb_w = tf.get_variable('r_width', shape=(2*w - 1, dim),dtype=q.dtype,initializer=tf.random_normal_initializer(int_dim**-0.5))rel_logits_w = relative_logits_1d(q=q, rel_k=rel_emb_w,transpose_mask=[0, 1, 2, 4, 3, 5])# Relative logits in height dimension.rel_emb_h = tf.get_variable('r_height', shape=(2*h - 1, dim),dtype=q.dtype,initializer=tf.random_normal_initializer(int_dim**-0.5))rel_logits_h = relative_logits_1d(q=tf.transpose(q, [0, 1, 3, 2, 4]),rel_k=rel_emb_h,transpose_mask=[0, 1, 4, 2, 5, 3])return rel_logits_h + rel_logits_wdef relpos_self_attention(*, q, k, v, relative=True, fold_heads=False):"""2D self-attention with rel-pos. Add option to fold heads."""bs, heads, h, w, dim = q.shapeint_dim = dim.valueq = q * (dim ** -0.5) # scaled dot-productlogits = tf.einsum('bhHWd,bhPQd->bhHWPQ', q, k)if relative:logits += relative_logits(q)weights = tf.reshape(logits, [-1, heads, h, w, h * w])weights = tf.nn.softmax(weights)weights = tf.reshape(weights, [-1, heads, h, w, h, w])attn_out = tf.einsum('bhHWPQ,bhPQd->bHWhd', weights, v)if fold_heads:attn_out = tf.reshape(attn_out, [-1, h, w, heads * dim])return attn_out
下載
在極市平臺公眾號后臺回復:BoTNet,即可獲得論文與code下載鏈接(注:暫無預訓練模型)。
? 推薦閱讀
搞懂 Vision Transformer 原理和代碼,看這篇技術綜述就夠了(一)
搞懂 Vision Transformer 原理和代碼,看這篇技術綜述就夠了(二)
Transformer再下一城!low-level多個任務榜首被占領,北大華為等聯(lián)合提出預訓練模型IPT

