RepVGG: Making VGG-style ConvNets Great Again
作者:elfin 資料來源:RepVGG論文解析
1、摘要
我們提出了一種簡單而強大的卷積神經網絡結構,它具有類似VGG的推理結構,僅由3×3卷積和ReLU組成,而訓練模型具有多分支拓撲結構。這種訓練和推理結構的解耦是通過一種結構參數重構技術(structural re-parameterization)來實現的,因此該模型被命名為RepVGG。在ImageNet上,RepVGG達到了80%以上的top-1精度,據我們所知,這是第一次使用普通模型。在nvidia1080TI gpu上,RepVGG模型的運行速度比ResNet-50快83%,比ResNet-101快101%,精度更高,與EfficientNet和RegNet等最先進的模型相比,顯示出良好的精度-速度折衷。
項目地址:https://github.com/megvii-model/RepVGG
pytorch版本:https://github.com/DingXiaoH/RepVGG
2、背景介紹
卷積神經網絡(ConvNets)已成為解決許多問題的主流方法。VGG在圖像識別方面取得了巨大的成功,但是它僅使用了一個由conv、ReLU和pooling組成的簡單體系結構。隨着Inception、ResNet和DenseNet的出現,許多研究興趣轉移到了設計良好的體系結構上,使得模型變得越來越復雜。最近一些強大的架構是通過自動或手動的架構搜索,或者在一個基本架構上搜索一個復合縮放策略來獲得的。
雖然許多復雜的卷積網絡比簡單的卷積網絡提供更高的精度,但缺點是顯著的:
- (1) 復雜的多分支設計(如ResNet中的殘差分支 和 Inception中的分支級聯)使得模型難以實現和定制,降低了推理速度,降低了內存利用率。
- (2) 一些組件增加了內存訪問成本,並且缺乏對各種設備的支持(例如,Xception和MobileNets 中的depthwise 以及ShuffleNets中的通道shuffle。
由於影響推理速度的因素很多,浮點運算(FLOPs)的數量並不能准確反映實際速度。盡管一些新的模型比老式的VGG和ResNet有更低的浮點運算,但是他們可以運行速度並不快。下表展示了運行速度的變換:
因此,VGG和ResNets的原始版本仍然大量用於學術界和工業界的實際應用。
在本文中,我們提出了RepVGG,這是一種VGG風格的結構,它優於許多復雜的模型,如圖所示:
RepVGG的優點有:
- 該模型有一個類似VGG的拓撲結構,沒有任何分支。也就是說,每一層都將其前一層的輸出作為輸入,並將輸出輸入到其后一層。
- 模型僅使用 \(3 \times 3\) 的卷積結構和\(ReLU\)激活。
- 具體的架構(包括特定的深度和層寬度)是沒有自動搜索、手動細化、復合縮放,也沒有其他繁重設計的實例化。
普通模型要達到與多分支體系結構相當的性能水平是一個挑戰。一種解釋是,多分支拓撲(例如ResNet)使模型成為許多較淺模型的隱式集合,因此訓練多分支模型可以避免梯度消失問題。
由於多分支結構的優點都是用於訓練,缺點是不希望用於推理,因此我們提出通過結構參數重構將訓練多分支結構和推理結構解耦,即通過參數轉換將結構從一個結構轉換為另一個結構。具體而言,網絡結構與一組參數耦合,例如,conv層由四階核張量表示。如果某個結構的參數可以轉換成另一個結構耦合的另一組參數,就可以等價地用后者代替前者,從而改變整個網絡結構。
具體地說,我們使用identity和1×1分支構造RepVGG的訓練結構,這是受ResNet啟發的,但不同的方法是通過結構參數重構去除分支(如下圖所示)。經過訓練后,我們用簡單代數進行變換,因為一個恆等分支可以看作退化的1×1變換,后者可以進一步看作退化的3×3變換,所以我們可以用原3×3核的訓練參數構造一個3×3核,identity分支和1×1分支和批量規范化(BN)層。因此,轉換后的模型是一個3×3 conv層的堆棧,可以保存以供測試和部署。
值得注意的是,RepVGG的推理主體只涉及一種操作類型:3×3 conv,然后是ReLU,這使得RepVGG在gpu等通用計算設備上運行得很快。更好的是,RepVGG允許專用硬件實現更高的速度,因為考慮到芯片大小和功耗,我們需要的操作類型越少,我們可以集成到芯片上的計算單元就越多。即,專門用於RepVGG的推理芯片可以具有大量的3×3-ReLU單元和更少的存儲器單元(因為普通拓撲是存儲器經濟的,如圖3所示)。我們的貢獻總結如下:
- 我們提出了RepVGG,這是一種簡單的體系結構,與現有技術相比,它具有良好的速度精度折衷。
- 我們提出使用結構參數重構來將訓練多分支拓撲與推理結構解耦。
- 我們已經證明了RepVGG在圖像分類和語義分割方面的有效性,以及它的效率和易實現性。
3、相關工作
3.1 單分支到多分支
VGG網絡在ImgNet競賽中獲得最優的性能后,許多新的創新將其精確度進一步提高。如:GoogLeNet、Inception采用多分支結構; ResNet使用了簡單的二分支結構;DenseNet通過連接低層和多個高層,使得拓撲結構更加復雜。神經結構搜索(NAS)和人工設計空間設計可以產生性能更高的網絡,但代價是巨大的計算資源或人力。一些大版本的NAS生成模型甚至不能在普通gpu上訓練,因此限制了其應用。除了實現的不便外,復雜模型也會降低並行度,從而降低推理速度。
3.2 單分支模型的高效訓練
有人試圖訓練沒有分支的網絡。然而,以往的工作主要是為了使非常深的模型收斂到合理的精度,但並沒有取得比復雜模型更好的性能。因此,這些方法和模型既不簡單,也不實用。例如,提出了一種初始化方法來訓練極深的平面網絡。采用基於平均場理論的訓練方案,在MNIST上訓練了10000層網絡,訓練精度達到99%,在CIFAR-10上訓練精度達到82%。盡管這些模型並不實用(即使LeNet-5在MNIST上的准確率也能達到99.3%,VGG-16在CIFAR-10上的准確率也能達到93%以上),但其理論貢獻是深刻的。最近的一項工作[24]結合了幾種技術,包括 Leaky ReLU、最大范數和謹慎初始化。在ImageNet上,一個具有147M參數的普通ConvNet可以達到74.6%的top-1精度,比其報告的基線(ResNet-101,76.6%,45M參數)低2%。值得注意的是,本文不僅證明了普通模型可以很好地收斂,而且不打算像resnet那樣訓練極深的convnet。相反,我們的目標是建立一個具有合理深度和良好精度-速度權衡的簡單模型,該模型可以簡單地用最常見的組件(如正則conv和BN)和簡單代數實現。
3.3 模型參數重構
DiracNet[38]是一種與我們相關的參數重構方法。它通過把一個卷積層的卷積核編碼為:
其中\(\hat{W}\) 是卷積的最終權重,是一個四階的張量矩陣;\(W_{norm}\) 是標准化的kernel,\(\vec{a}\)、\(\vec{b}\) 是需要學習的向量。與殘差神經網絡相比,在性能方面,DiracNet在CIFAR-100數據集上要低 \(2.29\%\) ,ImageNet數據集上要低\(0.62\%\)。
DiracNet模型與RepVGG的差異為:
- 我們的結構參數重構是通過一個具體結構的實際數據流來實現的,這個具體結構以后可以轉換成另一個結構,而DiracNet僅僅使用另一個轉換核的數學表達式,以便於優化。也就是說,一個結構參數重構的平面模型是一個實時訓練的多分支模型,而DiracNet不是。
- DiracNet的性能高於通常參數化的普通模型,但低於可比較的ResNet,而RepVGG模型的性能遠遠優於ResNet。
Asym Conv Block(ACB)[9]采用非對稱Conv來加強規則Conv的“骨架”,這可以看作是結構參數重構的另一種形式,因為它將訓練的塊轉換為Conv。與我們的方法相比,不同之處在於,ACB是為組件級改進而設計的,並在任何體系結構中用作conv層的替換,而我們的結構重新參數化對於訓練普通convnet非常關鍵,如第4.2節所示。
3.4 Winograd(威諾格拉德)卷積
RepVGG只使用3×3 conv,因為它在GPU和CPU上都被一些現代計算庫(如NVIDIA cuDNN[1]和Intel MKL[16])高度優化。下表顯示了在1080TI GPU上用cudnn7.5.0測試的理論FLOPS、實際運行時間和計算密度(以每秒Tera(兆兆)浮點運算(TFLOPS)為單位)。結果表明,3×3conv的理論計算密度約為4倍,表明理論總的FLOPs數不能代表不同體系結構的實際速度。

加速3×3 conv的一個經典算法是Winograd算法[18](僅當步長為1時),它得到了cuDNN和MKL等庫的良好支持(默認情況下啟用)。例如,使用標准\(F(2 \times 2, 3 \times 3)\)的Winograd,3×3 conv的乘法量(mul)減少到原來的\(\frac{4}{9}\)。由於乘法要比加法耗時得多,所以我們計算Muls來度量Winograd支持下的計算開銷(后面會提到)。請注意,特定的計算庫和硬件決定是否對每個操作符使用Winograd,因為小規模的卷積可能不會由於內存開銷而加速。
4、由結構參數重構技術構建RepVGG
4.1 簡單即快速、內存使用經濟、靈活
使用簡單convnet至少有三個原因:它們速度快、內存經濟且靈活。
Fast 許多最近的多分支架構的理論 FLOPs比VGG低,但可能運行得不快。 VGG-16的 FLOPs是EffificientNet-B3的8.4倍,但是運行速度卻是其1.8倍,這意味着前者的計算密度為后者的15倍。除了Winograd conv帶來的加速外,FLOPs和速度之間的差異可歸因於兩個重要因素,它們對速度有相當大的影響,但FLOPs沒有考慮到這兩個因素:內存訪問成本(MAC)和並行度[23]。如:雖然所需的分支加法或級聯計算可以忽略不計,但MAC是重要的。此外,MAC在分組卷積中占很大一部分時間。另一方面,在相同的FLOPs條件下,一個高並行度的模型比另一個低並行度的模型要快得多。由於多分支拓撲結構被廣泛應用於初始和自動生成的體系結構中,因此使用多個小的操作符來代替幾個大的操作符。先前的一項工作[23]報告說,NASNET-A[42]中的分段運算符(即單個conv或池操作在一個構建塊中的數目)為13,這對GPU等具有強大並行計算能力的設備不友好,並引入額外的開銷,如內核啟動和同步。相反,在resnet中,這個數字是2或3,我們將它設為1:單個conv。
Memory-economical 多分支拓撲的內存效率很低,因為每個分支的結果都需要保留到加法或級聯之后,這大大提高了內存占用的峰值。剩余塊的輸入需要保持,直到添加為止。假設塊保持特征圖大小,則內存占用峰值為輸入的兩倍。相反,普通拓撲允許在操作完成時立即釋放特定層的輸入占用的內存。在設計專用硬件時,一個普通的ConvNet允許深度內存優化並降低內存單元的成本,這樣我們就可以將更多的計算單元集成到芯片上。
Flexible 多分支拓撲對體系結構規范施加了約束。ResNet要求conv層被組織為殘差塊,這限制了靈活性,因為每個殘差塊的最后一個conv層必須產生相同形狀的張量,否則快捷加法就沒有意義。更糟的是,多分支拓撲限制了channel修剪[20,12]的應用,這是一種去除一些不重要通道的實用技術,一些方法可以通過自動發現每層的適當寬度來優化模型結構[7]。然而,多分支模型使得剪枝變得棘手,並導致性能顯著下降或加速比低[6,20,8]。相反,簡單的體系結構允許我們根據需求自由配置每個conv層,並進行刪減以獲得更好的性能效率權衡。
4.2 訓練時的多分支結構
普通網絡有很多優點,但有一個致命的缺點:性能差。例如,有了像BN[17]這樣的現代組件,VGG-16可以在ImageNet上達到72%以上的top-1精度,這似乎已經過時了。我們的結構參數重構方法受到ResNet的啟發,它顯式地構造一個快捷分支,將信息流建模為\(y = x + f(x)\),並使用一個殘差塊來學習\(f\)。當 \(x\)與\(f(x)\)的維度不一樣時,公式變為\(y=g(x)+f(x)\),\(g(x)\)是一個\(1 \times 1\)的卷積。resnet成功的一個解釋是,這種多分支架構使模型成為眾多較淺模型的隱式集合[35]。特別地,對於n個塊,模型可以解釋為2n個模型的集合,因為每個塊將流分支成兩條路徑。由於多分支拓撲在推理上有缺陷,但分支似乎有利於訓練[35],我們使用多個分支來對眾多模型進行訓練的集成。
為了使大多數成員更淺或更簡單,我們使用ResNet-like恆等式(僅當維度匹配時)和\(1×1\)分支,使得構建塊訓練時的信息流為
我們簡單地堆疊幾個這樣的區塊來建構訓練時間模型。(注意,這樣信息流中的結構在每層都一樣,運算的時候就更快了)
從與[35]相同的角度來看,模型變成了一個由n個block生成的\(3^{n}\)個成員組成的集合。訓練后等價地轉化為\(y=h(x)\),其中h由一個conv層實現,其參數通過訓練后的一系列代數參數導出。
4.3 推理時的模型參數重構
這里我們將介紹把\(y=x+g(x)+f(x)\)結構轉換為\(y=h(x)\)結構。需要注意的是每一個分支在合並(相加)之前都使用了BN層。
一般地,我們假設輸入channel為\(C_{1}\),輸出通道為\(C_{2}\),則\(3 \times 3\)的卷積核的權值矩陣為:
對於\(1 \times 1\)的分支, \(1 \times 1\)的卷積核的權值矩陣為:
我們使用\(\boldsymbol{\mu}^{(3)}, \boldsymbol{\sigma}^{(3)},\boldsymbol{\gamma}^{(3)}, \boldsymbol{\beta}^{(3)}\)分別表示\(3 \times 3\)之后BN層的累計均值、標准差、縮放因子、偏置;
我們使用\(\boldsymbol{\mu}^{(1)}, \boldsymbol{\sigma}^{(1)},\boldsymbol{\gamma}^{(1)}, \boldsymbol{\beta}^{(1)}\)分別表示\(1 \times 1\)之后BN層的累計均值、標准差、縮放因子、偏置;
我們使用\(\boldsymbol{\mu}^{(0)}, \boldsymbol{\sigma}^{(0)},\boldsymbol{\gamma}^{(0)}, \boldsymbol{\beta}^{(0)}\)分別表示identity分支的累計均值、標准差、縮放因子、偏置;
令\(M^{(1)} \in \mathbb{R}^{N\times C_{1}\times H_{1}\times W_{1}}\)表示輸入,\(M^{(2)} \in \mathbb{R}^{N\times C_{2}\times H_{2}\times W_{2}}\)表示輸出。\(*\)表示卷積操作。
如果\(C_{1}=C_{2}, H_{1}=H_{2}, W_{1}=W_{2}\),則有:
否則,我們簡單地不使用恆等映射分支,因此上面的方程只有前兩項。對\(\forall 1\leq i\leq C_{2}\):
我們首先將每一個BN及其前一個conv層轉換為帶有偏置向量的conv。令\(\left \{{W}',{\boldsymbol{b}}' \right \}\)表示從\(\left \{W,\boldsymbol{\mu}, \boldsymbol{\sigma}, \boldsymbol{\gamma}, \boldsymbol{\beta} \right \}\)轉換的kernel和bias,則有:
因此,容易驗證對\(\forall 1\leq i\leq C_{2}\):
上述變換也適用於identity分支,因為identity 特征圖可以看作是以單位矩陣為核的1×1變換。在這樣的變換之后,我們將有一個3×3核、兩個1×1核和三個偏置向量。然后我們將三個偏差向量相加得到最終偏差,將1×1的核加到3×3核的中心點得到最終的3×3核,這很容易實現,首先將兩個1×1核置零到3×3,然后將三個核相加,如下圖所示。注意,這種變換的等價性要求3×3和1×1層具有相同的步幅,並且后者的填充配置應比前者少一個像素。例如,對於將輸入填充一個像素的3×3層(這是最常見的情況),1×1層的填充應為0。

4.4 結構規格
下表展示了RepVGG的規格,包括深度和寬度。RepVGG是VGG風格的平面網絡,且大量使用\(3 \times 3\)的卷積,但是沒有像VGG網絡那樣使用最大池化,因為設計這種網絡只使用一種操作,可以加快運行速度。所有的stage都使用Repblock替換了\(3 \times 3\)的卷積,每層的第一個卷積操作,進行下采樣。對於圖像分類,使用全局平均池化接全連接層,作為head。對於其他任務,任務特定的頭可以用所有層生成的特征。

關於每個stage的layer數量,主要由如下的三個原則確定:
- 第一級的分辨率很高,非常耗時,因此我們只使用一層來降低延遲。
- 最后一級應該有更多的通道,所以我們只使用一層來保存參數。
- 我們將大多數層放在倒數第二個stage(在ImageNet上具有\(14 \times 14\)的輸出分辨率),跟隨ResNet及其最新變體。(如,ResNet-101使用了69個layer在\(14 \times 14\)的階段)
最后,我們對5個stage的層數分配是:[1, 2, 4, 14, 1],並命名為RepVGG-A。我們也構建了一個更深的RepVGG-B,在stage2、stage3、stage4都增加了2層。
RepVGG-A用於和其他輕量級的模型進行比較;RepVGG-B用於和ResNet-18/34/50這種中等體量的模型進行比較 。當然RepVGG-B取得了更好的性能表現。
我們通過均勻縮放經典寬度設置[64、128、256、512]來確定層寬度。我們使用乘數a來縮放前四個階段,b來縮放最后一個階段,並且通常設置b>a,因為我們希望最后一層對於分類或其他下游任務具有更豐富的特征。由於RepVGG在最后一個階段只有一個層,因此較大的b不會顯著增加延遲或參數量。具體地 stage2、3、4、5的寬度分別為[64a、128a、256a、512b]。
為了避免大特征圖上的大卷積,如果\(a < 1\),我們縮小stage1,但不放大它,因此stage1的寬度是\(min\left ( 64, 64a \right )\)。
為了進一步減少參數和計算量,我們可以選擇將分組的3×3 conv層與密集的conv層交錯,以精度換取效率。具體來說,我們為RepVGG-A的第3、5、7、…、21層以及RepVGG-B的附加第23、25和27層設置groups數目為\(g\)。為了簡單起見,我們將\(g\)全局設置為1、2或4,沒有按層調整。我們不使用相鄰的groupwise conv層,因為這將禁用通道間的信息交換並帶來副作用:某個通道的輸出只能從輸入通道的一小部分中導出。注意,1×1分支應具有與3×3 conv相同的groups數目為\(g\)。
完