CVPR2022 | A ConvNet for the 2020s & 如何設計神經網路總結

語言: CN / TW / HK

前言 本文深入探討了如何設計神經網路、如何使得訓練神經網路具有更加優異的效果,以及思考網路設計的物理意義。

歡迎關注公眾號CV技術指南,專注於計算機視覺的技術總結、最新技術跟蹤、經典論文解讀、CV招聘資訊。

論文:http://arxiv.org/pdf/2201.03545.pdf

程式碼: http://github.com/facebookresearch/ConvNeXt

引言

VIT問世以後,Swin Transformer在影象領域(分類下游任務)的全面大幅度超越 CNN 模型,彷彿印證了 Attetion 論文中 “Attention Is All You Need ”。

ConvNext這篇論文,通過借鑑Swin Transformer精心構建的 tricks,使得卷積在影象領域反超了Transformer。這些技巧對分類問題的下游問題也有效果。不禁令人深思,在深度學習中如何設計網路,如何使得訓練神經網路具有更加優異的效果,以及思考網路設計的物理意義(儘管到現在為止很多網路模型的構建可能更多來源於“靈感”之類的)。

ConvNeXt借鑑了以下tricks:

1. 訓練技巧、預訓練和網路結構比例

2. 減少啟用層和歸一化層的使用(Relu和Norm會造成特徵損失)

3. 運用了7*7大尺寸的卷積核且效果更優(由於運用了Inverted Bottleneck和depth-wise Convs使得計算量基本穩定的情況下增加了效能)

4. 分離的下采樣層和LN層。

一、Swin-Transformer介紹

1.1、Swin-Transformer背景介紹

自從ViT提出之後,在過去的一年裡(2021年),基於transformer的模型在計算機視覺各個領域全面超越CNN模型。然而,這很大程度上都歸功於Local Vision Transformer模型,Swin Transformer是其中重要代表。

原生的ViT模型其計算量與影象大小的平方成正比,而Local Vision Transformer模型由於採用local attention(eg. window attention),其計算量大幅度降低。

除此之外,Local Vision Transformer模型往往也採用金字塔結構,這使得它更容易應用到密集任務如檢測和分割中,因為密集任務往往輸入影象解析度較高,而且也需要多尺度特徵(eg. FPN)。

總而言之,Swin Transformer 將計算量降低,引入 CNN 多尺度結構,使 Transformer 能夠解決分類下游問題。

1.2、CNN網路的反擊

1.2.1、Depth-wise conv的反擊

微軟在去年6年份的工作已經討論了用7x7 depth-wise conv模擬Local Vision Transformer,並且實現了比Swin Transformer更好的效果。微軟在論文Demystifying Local Vision Transformer: Sparse Connectivity, Weight Sharing, and Dynamic Weight上系統地總結了Local Vision Transformer的三大特性:

Sparse connectivity:每個token的輸出只依賴於其所在local window上tokens,而且各個channel之間是無聯絡的;(這裡忽略了attention中query,key和valude的linear projections,那麼attention就其實可以看成在計算好的權重下對tokens的特徵進行加權求和,而且是channel-wise的);

Weight sharing:權重對於各個channel是共享的;

Dynamic weight:權重不是固定的,而是基於各個tokens動態生成的。

這樣總結的話,local attention就和depth-wise convs存在很多的相似之處。首先後者也具有Sparse connectivity:計算只在kernel size範圍內,而且各個channel之間無連線。然後depth-wise convs也具有weight sharing特性,但是卷積核是在所有的空間位置上共享的,而且不同channle採用不同的卷積核。對於第三點,depth-wise conv的卷積核是訓練引數,一旦完成訓練就是固定的,而不像attention那樣是動態的。但是local attention丟失了位置資訊,需要位置編碼,而depth-wise convolution則不需要。

下面是不同操作的區別:

1.2.2、ConvNeXt

MetaAI在論文A ConvNet for the 2020s中, 從ResNet出發並借鑑Swin Transformer提出了一種新的 CNN 模型:ConvNeXt,其效果無論在影象分類還是檢測分割任務上均能超過Swin Transformer,而且ConvNeXt和vision transformer一樣具有類似的scalability(隨著資料量和模型大小增加,效能同比提升)。

二、ResNet到ConvNeXt

ConvNeXt 從原始的 ResNet 出發,逐步加入swin transform 的 trick,來改進模型。論文中適用 ResNet模型:ResNet50和ResNet200。其中ResNet50和Swin-T有類似的FLOPs(4G vs 4.5G),而ResNet200和Swin-B有類似的FLOPs(15G)。

首先做的改進是調整訓練策略,然後是模型設計方面的遞進優化:巨集觀設計->ResNeXt化->改用Inverted bottleneck->採用large kernel size->微觀設計。由於模型效能和FLOPs強相關,所以在優化過程中儘量保持FLOPs的穩定。

模型效果提升 tricks 總覽:

2.1、訓練策略

原生的ViT需要大規模資料的預訓練,而MetaAI在DeiT論文中提出了一種增強版本的訓練策略來解決這個問題,這個訓練策略也被隨後的vision transformer模型所採用。

對於ResNet50,其訓練策略比較簡單(torchvision版本):batch size是32*8,epochs為90;優化器採用momentum=0.9的SGD,初始學習速率為0.1,然後每30個epoch學習速率衰減為原來的0.1;正則化只有L2,weight decay=1e-4;資料增強採用隨機縮放裁剪(RandomResizedCrop)+水平翻轉(RandomHorizontalFlip)。

而DeiT的訓練策略則非常heavy:採用了比較多的資料增強如Mixup,Cutmix和RandAugment;訓練的epochs增加至300;訓練的optimizer採用AdamW,學習速率schedule採用cosine decay;採用 smooth label 和EMA等優化策略。

這裡直接將DeiT的訓練策略(具體引數設定如下表)應用在ResNet50模型,其效能從原來的76.1%提升至78.8%(+2.7)。這也說明vision transformer模型相比CNN模型的提升很多程度上歸功於訓練策略的優化,關於這個問題,另外一篇論文Visformer也論證過這一點,而且最近timm庫和torchvison庫也分別釋出了ResNet新的訓練策略,並將ResNet50的效能提升至80%+。

我們框架中也可能存在adam優化器的問題, 2014年被提出的Adam優化器的收斂性被證明是錯誤的,之前大部分機器學習框架中對於Adam的權重衰減的實現也都是錯誤的。實際上,L2正則化和權重衰減在大部分情況下並不等價,只在SGD優化的情況下是等價的。而大多數框架中對於Adam+L2正則使用的是權重衰減的方式,兩者不能混為一談。

在 ConvNeXt 使用模型與訓練的方法, 如下:

2.2、Changing stage compute ratio

Swin Transfomer和CNN一樣也採用金字塔結構:包含4個stage,每個stage輸出不同尺度的特徵。這裡考慮Swin Transformer和ResNet在巨集觀設計上的區別,主要有兩點:每個stage的計算量佔比以及 stem cell結構(即stage1之前的模組)。

首先是各個stage的計算量佔比,對比ResNet50,4個stage的blocks數量分別是(3,4,6,3),而Swin-T的設定為(2,2,6,2),4個stage的計算量比約為1:1:3:1。這裡調整ResNet50各個stage的blocks數量以和Swin-T一致:從原來的(3,4,6,3)調整至(3,3,9,3)。

調整之後模型效能從78.8%提升至79.4%,不過這裡要注意的一點是,調整後其實blocks數量增加了,模型的FLOPs從原來的4G增加至4.5G,基本和Swin-T一致了,所以這個效能的提升很大程度上歸功於FLOPs的增加。

關於各個stage的計算量分配,並沒有一個理論上的參考,不過RegNet和EfficientNetV2論文中都指出,後面的stages應該佔用更多的計算量。

第二個就是stem的區別。對於Swin-T模型,其stem是一個patch embedding layer,實際上就是一個stride=4的4x4 conv。而 ResNet50的stem相對更復雜一些:首先是一個stride=2的7x7 conv,然後是一個stride=2 的 3x3 max pooling。

兩種stem最後均是得到1/4大小的特徵,所以這裡可以直接用Swin的stem來替換ResNet的stem,這個變動對模型效果影響較小:從79.4%提升至79.5%,可能是去掉最大池化起到了作用 ,最大池化會造成特徵損失。

對於ViT模型,其 patch size一般較大(eg. 16),只採用一個stride較大的conv來做patch embedding往往會存在一定問題,比如Mocov3論文中就指出patch embed可能會導致訓練不穩定,而論文Early Convolutions Help Transformers See Better指出將 patch embed 設計成幾個堆疊的 stride=2 的3*3 conv,無論是在模型效果上,還是在訓練穩定性以及收斂速度都更好;而Swin-T的 patch size相對較小,不會出現ViT的上述問題,不過Swin-T採用的是 non-overlapping conv,後面有論文指出採用overlapping conv(eg stride=4 的7x7 conv)會帶來一定的效能提升。

2.3、ResNeXt-ify (depth-wise)

相比 ResNet,ResNeXt通過採用group conv來提升效能,標準的conv其輸入是所有的channels,而group conv會對channels進行分組來減少計算量,這樣節省下來的計算量用來增加網路的width即特徵channels。對於group conv,其最極端的情況就是每個channel一個group,這樣就變成了depthwise conv(簡稱dw conv),dw conv首先在MobileNet中應用,後來也被其它CNN模型廣泛採用。

對於dw conv,其和 local attention 有很多的相似的地方,local attention其實就是對window裡的各個token的特徵做加權和,而且操作是per-channel的;而dw conv是對kernel size範圍的token的特徵求加權和,也是分channel的。這裡的最大區別就是:self-attention的權重是動態計算的(data dependent),而dw conv的權重就是學習的kernel。

這裡將 ResNet50中的 3x3 conv替換成3x3 dw conv,為了彌補 FLOPs 的減少,同時將 ResNet50 的 base width從原來的64增加至96(和Swin-T一致,這裡的base width是指stem後的特徵大小),此時模型的FLOPs有所增加(5.3G),模型效能提升至80.5%。

2.4、Inverted Bottleneck

如果把self-attention看成一個dw conv的話(這裡忽略self-attention的linear projection操作),那麼一個transformer block可以近似看成一個inverted bottleneck,因為MLP等效於兩個1x1 conv,並且MLP中間隱含層特徵是輸入特徵大小的4倍(expansion ratio=4)。

inverted bottleneck最早在MobileNetV2中提出,隨後的EfficientNet也採用了這樣的結構。ResNet50採用的是正常的residual bottleneck,這裡將其改成inverted bottleneck,即從圖(a)變成圖(b),雖然dw conv的計算量增加了,但是對於包含下采樣的residual block中,用於shortcut的1x1 conv計算量卻大大降低,最終模型的FLOPs減少為4.6G。這個變動對ResNet50的影響較小(80.5%->80.6%)。

2.5、Large Kernel Sizes

自從VGG之後,主流的CNN往往採用較小的kernel size,如3x3和5x5,其中3x3 conv在GPU上有高效的實現。然而Swin-T採用的 window size為7x7,這比3x3 conv對應的 window size要大得多,所以這裡考慮採用更大的kernel size。

在這之前,首先將dw conv移到inverted bottleneck block的最開始,如上圖(c)所示。對於transformer block,其實self-attention也是在開始,同時由於採用inverted bottleneck,將dw conv移動到最前面可以減少計算量(4.1G),後續採用較大的kernel size後模型的FLOPs變動更少。

由於模型FLOPs的降低,模型效能也出現一定的下降:80.6%->79.9%。然後調整dw conv的kernel size,這裡共實驗了5種kernel size:3x3,5x5,7x7,9x9和11x11。

實驗發現kernel size增加,模型效能有提升,但是在7x7之後採用更大的kernel size效能達到飽和。所以最終選擇7x7,這樣也和Swin-T的window size一致,由於前面的dw conv位置變動,採用7x7的kernel size基本沒帶來FLOPs的增加。採用7x7 dw conv之後,模型的效能又回到 80.6%。

2.6、微觀設計

2.6.1 ReLU -> GreLU

經過前面的改動,模型的效能已經提升到80%以上,此時改動後的ResNet50也和Swin-T在整體結構上很類似了,下面我們開始關注一些微觀設計上的差異,或者說是layer級別的不同。

首先是啟用函式,CNN模型一般採用ReLU,而transformer模型常常採用GELU。這裡把啟用函式都從ReLU改成GELU,模型效果沒有變化(80.6%)。

2.6.2 減少啟用層和歸一化層

如下圖示,這裡只保留中間1x1 conv之後的GELU,就和Swin-T基本保持一致了,這個變動使模型效能從80.6%提升至81.3%。

對於norm層,也存在和啟用函式一樣的問題,transformer中只在self-attention和MLP的開始採用了LayerNorm,而ResNet每個conv之後採用BatchNorm,比transformer多一個norm層。這裡去掉其它的BatchNorm,只保留中間1x1 conv前的BatchNorm,此時模型效能有0.1%的提升。實際上要和 transformer 保持一致,應該在block最開始增加一個BatchNorm,但是這個並沒有提升效能,所以最終只留下了一個norm層。

另外,transformer的norm層採用 LayerNorm,而CNN常採用BatchNorm,一般情況下BatchNorm要比LayerNorm效果要好,但是BatchNorm受batch size的影響較大。這裡將BatchNorm替換成LayerNorm後,模型效能提升至81.5%。

最後一個差異是下采樣,ResNet中的下采樣一般放在每個stage的最開始的block中,採用 stride=2 的3x3 conv;但是ConvNeXt 採用分離的下采樣去近似 Swin Transform的 Patch Merging layer(可以看補充知識去理解 Patch Merging),即下采樣是放在兩個stage之間,通過一個stride=2的 2x2 conv。

但是實驗發現,如果直接改用Swin-T的下采樣,會出現訓練發散問題,解決的辦法是在新增幾個norm層:在stem之後,每個下采樣層之前以及global avg pooling之後都增加一個LayerNom(Swin-T也是這樣做的)。最終模型的效能提升至82.0%,超過Swin-T(81.3%)。

2.7、其它資料

前面我們從ResNet50的Swin-T化,最終得到了ConvNeXt-T模型,對於更大的模型,可以通過調整特徵的維度C和各個stage的blocks數量。論文共設計5個ConvNeXt模型,其中前4個模型分別對標Swin,而最後ConvNeXt-XL是一個更大的模型,用來驗證模型的scalability。

ConvNeXt-T: C = (96, 192, 384, 768), B = (3, 3, 9, 3)

ConvNeXt-S: C = (96, 192, 384, 768), B = (3, 3, 27, 3)

ConvNeXt-B: C = (128, 256, 512, 1024), B = (3, 3, 27, 3)

ConvNeXt-L: C = (192, 384, 768, 1536), B = (3, 3, 27, 3)

ConvNeXt-XL: C = (256, 512, 1024, 2048), B = (3, 3, 27, 3)

ConvNeXt在ImageNet1K資料集上的分類效果如下所示,可以看到,ConvNeXt在不同的FLOPs均可以超過Swin,如果採用ImageNet22K預訓練後,模型效能有進一步的提升,其中ConvNeXt-XL可以達到87.8%,僅略低於目前的SOTA一點(MViT-H, 512^2,88.8%,只有ImageNet21K)。

在下游任務檢測和分割上,ConvNeXt也可以超過Swin,如下表所示:

由於FLOPs往往不能準確地反映實際的推理速度,所以上面的對比結果也包括模型速度(分類上用throughout,檢測上用FPS),可以看到在實際推理速度上,ConvNeXt也略好於Swin。

在視訊記憶體使用上,兩者也相當,比如基於ConvNeXt-B的Cascade Mask-RCNN需要17.4GB peak memory,而Swin-B 需要18.5GB。另外,如果在A100上(支援TF32),採用channel last,ConvNeXt相比Swin有明顯的速度優勢:

Robustness Evaluation , ConVNeXt 也優於 swin-Transform

尋找一位對目標檢測非常熟悉的朋友,對目標檢測從傳統方法到深度學習的所有大總結,主要包括傳統方法檢測、RCNN系列、YOLO系列、anchor-free系列、小目標檢測方法總結、小樣本目標檢測方法總結、視訊中的目標檢測方法總結、目標檢測使用的損失函式總結等內容。支援邊學邊寫。有一定的稿費與福利,具體請聯絡本人詳談(掃描連結中的二維碼)。同理也包括影象分割、Transformer等方向。

CV技術指南建立了一個計算機視覺技術交流群和免費版的知識星球,目前星球內人數已經600+,主題數量達到200+。

知識星球內將會每天釋出一些作業,用於引導大家去學一些東西,大家可根據作業來持續打卡學習。

技術群內每天都會發最近幾天出來的頂會論文,大家可以選擇感興趣的論文去閱讀,持續follow最新技術,若是看完後寫個解讀給我們投稿,還可以收到稿費。

另外,技術群內和本人朋友圈內也將釋出各個期刊、會議的徵稿通知,若有需要的請掃描加好友,並及時關注。

加群加星球方式:關注公眾號CV技術指南,獲取編輯微信,邀請加入。

歡迎關注公眾號CV技術指南,專注於計算機視覺的技術總結、最新技術跟蹤、經典論文解讀、CV招聘資訊。

其它文章

計算機視覺入門路線

CVPR2022 | iFS-RCNN:一種增量小樣本例項分割器

CVPR2022 | Time 3D:用於自動駕駛的端到端聯合單目三維物體檢測與跟蹤

CVPR2022 | A ConvNet for the 2020s & 如何設計神經網路總結

CVPR2022 | PanopticDepth:深度感知全景分割的統一框架

CVPR2022 | 重新審視池化:你的感受野不是最理想的

CVPR2022 | 未知目標檢測模組STUD:學習視訊中的未知目標

CVPR2022 | 基於排名的siamese視覺跟蹤

CVPR2022 | 通過目標感知Transformer進行知識蒸餾

CVPR2022丨無監督預訓練下的視訊場景分割

PyTorch CPU效能優化(二):並行化優化

PyTorch CPU效能優化(一):Memory Format 和 Channels Last 的效能優化

從零搭建Pytorch模型教程(六)編寫訓練過程和推理過程

從零搭建Pytorch模型教程(五)編寫訓練過程--一些基本的配置

從零搭建Pytorch模型教程(四)編寫訓練過程--引數解析

從零搭建Pytorch模型教程(三)搭建Transformer網路

從零搭建Pytorch模型教程(二)搭建網路

從零搭建Pytorch模型教程(一)資料讀取

一份熱力圖視覺化程式碼使用教程

一份視覺化特徵圖的程式碼

關於快速學習一項新技術或新領域的一些個人思維習慣與思想總結