博客專欄

EEPW首頁 > 博客 > 綜述:輕量級CNN架構(gòu)設計(3)

綜述:輕量級CNN架構(gòu)設計(3)

發(fā)布人:計算機視覺工坊 時間:2021-09-14 來源:工程師 發(fā)布文章

·  ShuffleNet系列

曠視出品的ShuffleNet系列有兩篇論文,且后一篇在打前一篇的臉,很有意思。

1.ShuffleNet V1是在MobileNet V1后MobileNet V2前提出的,說實話結(jié)構(gòu)上和MobileNet V2還挺像,大家可以上下兩張圖片對比一下。兩者都想到了學習ResNet的殘差結(jié)構(gòu),區(qū)別在于ShuffleNet V1覺得block當中的1×1標準卷積也非常耗時,于是用1×1的分組卷積外加channel shuffle的操作給替換了,然后MobileNet V2會先升維讓深度可分離卷積得到充分的學習再降維回來,ShuffleNet V1中stride為2的模塊也有自己的特色,雖然看著MobileNet V2的結(jié)構(gòu)更簡潔一些,但ShuffleNet V1創(chuàng)新也是不少,尤其那個用channel shuffle增強不同組之間信息交互的操作。

19.png

ShuffleNet V1

2. ShuffleNet V2論文是一篇誠意滿滿之作,作者通過分析ShuffleNet v1與MobileNet v2這兩個移動端網(wǎng)絡在GPU/ARM兩種平臺下的時間消耗分布,看出Conv等計算密集型操作占了絕大多數(shù)時間,但其它像Elemwise和IO等內(nèi)存讀寫密集型操作也占了相當比例的時間,因此像以往那樣僅以FLOPs來作為指導準則來設計CNN網(wǎng)絡是不完備的,雖然它可以反映出占大比例時間的Conv操作,但不夠準確。于是作者提出了高效網(wǎng)絡設計的四個指導原則:

1. 當輸入和輸出的通道數(shù)相同時,conv計算所需的MAC(memory access cost)最?。?/p>

2. 大量的分組卷積會增加MAC開銷;

3. 網(wǎng)絡結(jié)構(gòu)的碎片化會減少其可并行優(yōu)化的程度,GoogleNet系列和NASNet中很多分支進行不同的卷積/pool計算非常碎片,對硬件運行很不友好;

4. Element-wise操作不可忽視,對延時影響很大,包括ReLU,Addition,AddBias等,主要是因為這些操作計算與內(nèi)存訪問的占比太?。?/p>

基于此,作者提出了ShuffleNet V2的blocks,如下所示,與V1相比,去掉了分組卷積的操作,去掉了Add操作,換成了Concat,stride為2的block的旁路把平均池化換成了深度可分離卷積,為了繼續(xù)延續(xù)channel shuffle的操作,作者在block進去的地方做了個split的操作,最后再concat+channel shuffle,這里是為了替換掉之前的Add,同時也可以減少計算量。

20.png

ShuffleNet V2

Shift: A Zero FLOP, Zero Parameter Alternative to Spatial Convolutions

這是一篇很有意思的論文,主要是提出了一種無參數(shù),無計算的移位算子來代替ResNet中計算量占比很高的3×3卷積,這種算子稱為shift kernel,如下圖所示,只需要根據(jù)kernel上的shift信息對feature map進行位置上的上下左右偏移即可得到新的feature map,沒有計算,僅僅是訪存操作。詳細一點說就是如下面Shift框里面的第一個卷積核,它只在黃色的區(qū)域為1,其他白色的區(qū)域為0,在做卷積計算的時候其實就相當于把輸入feature map中間偏左邊的那個點的值平移到輸出feature map中間的地方,正如作者標注的向右的箭頭所示。而且這個操作都是per-channel的,所以每個卷積核只有k×k種可能性,當通道數(shù)大于k×k時,就需要將所有通道分成iC/(k×k)組,剩下的channel設置為center,即中間為1,其余為0,然后怎么去選取每個卷積核的類型呢,論文在兩個shift kernel中間夾了一個1×1的標準卷積,要保證第二次shift操作之后數(shù)據(jù)與第一次輸入shift kernel之前順序一致,并且這個shift操作可以通過SGD的方式進行端到端訓練,再具體的細節(jié)論文其實也沒有闡述的很清楚,而且我目前也沒有看到作者公布源代碼,不過這篇論文看起來還是很有意思的,論文中還分析了depthwise計算不高效的原因在于計算/IO時間導致運行更慢的問題,其實這個shift kernel的作用并沒有產(chǎn)生新的信息或者去進行特征的學習(畢竟連參數(shù)都沒有),而是對feature map空域的信息做了個混洗,使得與他相接的1×1卷積可以學到更豐富的特征,在我看來有點類似于在網(wǎng)絡內(nèi)部做數(shù)據(jù)增強的感覺。

21.png

Shift

· GhostNet

GhostNet也是一篇很有意思且簡潔的架構(gòu)設計的論文,作者在可視化一些訓練好的神經(jīng)網(wǎng)絡中間feature map時發(fā)現(xiàn)它們通常會包含一些相似且冗余的特征圖,使得神經(jīng)網(wǎng)絡能得到更充分的學習?;谶@個想法,作者通過設定一系列廉價的線性運算操作來代替部分卷積計算,以此來產(chǎn)生更多的特征圖,僅僅這么一個簡單的操作就可以減少模型的參數(shù)量和計算量,而且在幾個視覺公開數(shù)據(jù)集上取得了很不錯的效果,甚至超越了MobileNet V3,感覺非常的大道至簡,這也是我比較喜歡的原因。

22.png

GhostNet

基于特定硬件的神經(jīng)架構(gòu)搜索

基于特定硬件的神經(jīng)架構(gòu)搜索(MIT HAN Lab論文總結(jié)

https://zhuanlan.zhihu.com/p/320290820)

設計方法總結(jié)

接下來我將結(jié)合自己看過的論文,還有這一年多的項目比賽經(jīng)歷談一談我所理解的圖像分類和目標檢測相關輕量級模型設計,本文思想還比較淺薄,主要是給自己的工作做個總結(jié),有不正確的地方希望大家能共同討論。

設計之前

通常我們都是基于已有的硬件架構(gòu)去進行模型的部署,這個時候就需要確定這個架構(gòu)下能部署什么算子,可以通過已有的接口自己拓展哪些算子,并且哪些算子不是很高效。就拿我去年參加的某視覺加速比賽來說,當時初出茅廬,不太懂硬件底層,頭鐵要在Xilinx ultra96 V1板子 + 我們組自研的硬件架構(gòu)上部署當時最新,準確率最高的EfficientNet,因為準確率確實高,老板就欽定必須使用這個模型,并且選擇了比較合適的EfficientNet-B4,輸入分辨率由384改成256。后來一頓開搞發(fā)現(xiàn)有很多swish操作,這個雖然之前還沒有經(jīng)驗,但是還好很快想到用查找表去實現(xiàn)了,并且還發(fā)現(xiàn)我們的架構(gòu)尚且不能實現(xiàn)全連接層(勿噴,之前都是在搞全卷積網(wǎng)絡),所以里面的SE block還有最后一層都無法用我們的架構(gòu)部署,然后博士師兄就想到了利用ultra96板子上的ARM+NEON加速技術去實現(xiàn)這一部分,每次PS和PL交互數(shù)據(jù),當時只有一個月的開發(fā)時間,因為這個模型比較大且當時我們開發(fā)模式的問題,連續(xù)熬夜差點沒把整個組人的命搭進去,最后上板跑幀率也只有6幀(師兄最開始預估能達到80幀,所以大家一直不停的往下做hhhhh),在ImageNet驗證集上純浮點準確率是0.805,INT8準確率是0.793,幀率低的原因有兩點,一個是模型確實很大,另一個是因為SE block在每一個stride為1的module中都出現(xiàn)了,整個模型PS和PL交互十分頻繁,而我們當時間很緊剛剛完成一版就必須提交了,所以這塊也根本沒有優(yōu)化,導致了延時很高,并且當時我們的架構(gòu)只跑了100M的頻率,更高頻率會有一些bug(貌似是板子的問題),所以幀率非常低,這個真的是血的教訓:一定要量力而行,仔細研究評價指標,在硬件友好程度和精度上做一個trade-off,一味片面地追求精度真的要命呀。

輕量級CNN架構(gòu)設計

總的思路: 選定合適結(jié)構(gòu) + 通道剪枝 + 量化

訓練 :ImageNet pretrain model + Data Normalization(統(tǒng)計自己數(shù)據(jù)集的均值和方差) + Batch Normlization + 大batch size + 一堆數(shù)據(jù)增強tricks + 嘗試各種花里胡哨的loss function和optimizer

(再次說明這部分只討論圖像分類和目標檢測兩種任務,目前的視覺加速比賽基本都是基于這兩個任務做的,按照計算資源和內(nèi)存從小到大排列,不用問,沒有劃分原則)

1.絕對貧窮人口

輸入分辨率要小,如128,160,192或256;

下采樣使用MaxPooling;

特征學習層使用Depthwise Separable Convolution,即一層3×3的Depthwise + 一層pointwise(1×1標準卷積)堆疊;

激活函數(shù)用ReLU;

另外這里推薦看看MCUNet,感覺非常呦西,MIT韓松團隊yyds!

2. 相對貧窮人口

輸入分辨率依舊要小,記住分辨率對計算量的影響都是翻倍的;

下采樣可以使用MaxPooling或者stride為2的Depthwise Separable Convolution;

特征學習層使用Depthwise Separable Convolution,或者MobileNet V2的倒置殘差結(jié)構(gòu),又或是ShuffleNet V2的unit,1×1的Group convolution能處理的比較好的話其實也推薦使用(主要是計算/訪存);

激活函數(shù)用ReLU或者ReLU6;

3. 低收入人口

輸入數(shù)據(jù)選用小分辨率,如果對精度要求高一些可以適當增大;

下采樣可以使用MaxPooling或者stride為2的Depthwise Separable Convolution;

特征學習層可以使用MobileNet V2的倒置殘差結(jié)構(gòu),又或是ShuffleNet V2的unit,也可以使用通道數(shù)小一點的3×3標準卷積;

激活函數(shù)用ReLU,ReLU6或者leaky ReLU,看效果了;

4.一般收入人口

輸入數(shù)據(jù)可以稍微大一些,288,320,384啥的可以考慮上了;

下采樣使用stride為2的Depthwise Separable Convolution或者stride為2的3×3卷積;

特征學習層既可以使用上述的,也可以使用3×3標準卷積 + 1×1標準卷積的堆疊形式,SE block這種硬件支持的還不錯的可以嘗試加上;

激活函數(shù)除了上述的可以試試H-sigmoid和H-swish,不過據(jù)我經(jīng)驗效果基本和ReLU差不多;

5.高收入人口

輸入數(shù)據(jù)的分辨率可以往500-600靠攏了;

下采樣和上述一樣;

特征學習層可以上ResNet + SE block的配置,ResNet是真的牛逼,5×5的卷積啥的也可以整上,第一層直接上7×7的標準卷積也不是不可以,資源再多了可以增加通道數(shù)和深度 或者 上多核并行計算;

激活函數(shù)可以用H-swish;

番外

目標檢測任務中感覺Tiny YOLO V3非常受歡迎,建議嘗試!計算量太大可以換更輕量的backbone或者改輸入分辨率,輕量級的backbone+FPN的結(jié)構(gòu)也很棒,且推薦使用商湯開源的mmdetection,訓練調(diào)參當場起飛。

另外之前閱讀MIT HAN lab基于特定硬件的神經(jīng)架構(gòu)搜索相關文章時發(fā)現(xiàn)他們設計模型常用的一個子結(jié)構(gòu):MobileNetV2的倒置殘差模塊 + SE block + H-swish,看他們在很多算法加速比賽上拿了冠軍,感覺百試不爽呀,且根據(jù)硬件資源進行拓展的靈活度也很高,具體可以參見他們今年發(fā)表的OnceForAll論文中的模型,源代碼都在Github上能找到,MIT HAN lab真學術界良心,再喊一句MIT韓松團隊yyds!

最后總結(jié)

過去的一年被導師安排著參加各種比賽,去年啥也不懂的時候還能拿幾個不錯的獎,今年感覺學了很多懂了很多,使用的模型也都對硬件比較友好,量化后幾乎無損(一個點以內(nèi)),反倒連連受挫,心情非常沮喪,而且總被奇奇怪怪的模型打敗,總有一種自己學了一身正派功夫,最后反倒被野路子出招一擊即潰的感覺,然后論文也被拒了,沒心思改投,回想一下碰上疫情的這一年真的好失落,可能還是我太菜了吧。

馬上也要開始投入找實習(希望老板能放我)刷題找工作的階段了,最近也在培養(yǎng)下一屆,把工作慢慢移交給他們,一想到找工作,整個人的心態(tài)都不一樣了,無心科研,這篇文章就算是對我過去一年多的工作做個總結(jié)吧,同時也希望我們課題組能夠發(fā)展的越來越好,多多拿比賽大獎,多多發(fā)論文。

*博客內(nèi)容為網(wǎng)友個人發(fā)布,僅代表博主個人觀點,如有侵權(quán)請聯(lián)系工作人員刪除。

pid控制器相關文章:pid控制器原理




關鍵詞: AI

相關推薦

技術專區(qū)

關閉