ShuffleNet V2: Practical Guidelines for Efficient CNN Architecture Design

1. 摘要

最近,神經網絡的架構設計都是基於計算複雜度的間接度量,比如 FLOPs。然而,直接的度量比如運行速度,其實也會依賴於內存訪問和平臺特性等其它因素。

因此本文建議直接在目標平臺上用直接度量進行測試。基於一系列控制條件實驗,作者提出了設計高效網絡結構的一些實用指導思想,並據此提出了一個稱之爲 ShuffleNet V2 的新結構。

2. 介紹

爲了衡量計算複雜度,一個廣泛採用的度量方式是浮點運算的次數 FLOPs,但是,它是一個間接的度量,是對我們真正關心的直接度量比如速度或者時延的一種近似估計。在以前的工作中,這種不一致已經被學者們所發現,比如 MobileNet v2 要比 NASNET-A 快很多,但是它們兩者具有差不多的 FLOPs。

上圖中在 GPU 和 ARM 兩個平臺上,具有相同 FLOPs 的模型運行速度也會相差很多。因此只用 FLOPs 來衡量計算複雜度是不充分的,也會導致得不到最優的網絡設計。

導致這種不一致的主要有兩個原因:一是影響速度的幾個重要因素只通過 FLOPs 是考慮不到的,比如 MAC(Memory Access Cost)和並行度;二是具有相同 FLOPs 的模型在不同的平臺上可能運行速度不一樣。

因此,作者提出了設計有效網絡結構的兩個原則。一是用直接度量來衡量模型的性能,二是直接在目標平臺上進行測試。

3. 高效網絡設計的實用指導思想

首先,作者分析了兩個經典結構 ShuffleNet v1 和 MobileNet v2 的運行時間。

可以看到,雖然以 FLOPs 度量的卷積佔據了大部分的時間,但其餘操作也消耗了很多運行時間,比如數據輸入輸出、通道打亂和逐元素的一些操作(張量相加、激活函數)。因此,FLOPs 不是實際運行時間的一個準確估計。

G1:同樣大小的通道數可以最小化 MAC。

深度可分離卷積中的點卷積比如 1×1 佔據了大部分的複雜度。假設輸入的特徵圖大小爲 hwc1h*w*c_1,那麼輸出通道數爲 c2c_2 的 1×1 卷積的 FLOPs 爲 B=hwc1c2B=hwc_1c_2

簡單起見,我們假設計算設備的緩存足夠大能夠存放下整個特徵圖和參數。那麼內存訪問代價就爲 MAC=hw(c1+c2)+c1c2MAC=hw(c_1+c_2)+c_1c_2,這三項分別代表輸入特徵圖、輸出特徵圖和參數的代價。所以我們有:

MAC=hw(c1+c2)+c1c2=(hw)2(c1+c2)2+Bhw(hw)24c1c2+Bhw=2hwB+Bhw \begin{aligned} MAC&=hw(c_1+c_2)+c_1c_2 \\ &=\sqrt{(hw)^2(c_1+c_2)^2}+\frac{B}{hw}\\ &\geqslant\sqrt{(hw)^2 4c_1c_2}+\frac{B}{hw}\\ &=2\sqrt{hwB}+\frac{B}{hw} \end{aligned}

當且僅當 c1=c2c_1=c_2 時,MAC 取得最小值。但是這個結論只是理論上成立的,實際中緩存容量可能不夠大,緩存策略也因平臺各異。所以作者進一步設計了一個對比試驗來驗證,基準的網絡由 10 個塊組成,每個塊有兩層卷積,第一個卷積層輸入通道數爲 c1c_1 輸出通道數爲 c2c_2,第二層與第一層相反,然後固定總的 FLOPs 調整 c1:c2c_1:c_2 的值測試實際的運行速度,結果如下所示:

可以看到,當比值接近 1:1 的時候,網絡的測試速度最快。

G2:太多的分組卷積會增加 MAC。

分組卷積是現在網絡結構設計的核心,它通過通道之間的稀疏連接(也就是隻和同一個組內的特徵連接)來降低計算複雜度。一方面,它允許我們使用更多的通道數來增加網絡容量進而提升準確率,但另一方面隨着通道數的增多也對帶來更多的 MAC。

針對 1×1 的分組卷積,我們有:

B=hw11c1gc2gg=hwc1c2gB=h*w*1*1*\frac{c_1}{g}*\frac{c_2}{g}*g=\frac{hwc_1c_2}{g}
MAC=hw(c1+c2)+c1c2g=hwc1+Bgc1+BhwMAC=hw(c_1+c_2)+\frac{c_1c_2}{g}=hwc_1+\frac{Bg}{c_1}+\frac{B}{hw}

其中 BB 是需要的浮點數運算次數,gg 是分組卷積的組數,可以看到,如果給定輸入特徵圖的大小和計算代價,那麼 MAC 與組數成正比。作者通過疊加 10 個分組點卷積層設計了實驗,在保證計算代價相同的情況下采用不同的分組組數測試模型的運行時間,結果如下所示:

可以看到,分爲 8 個組要比 1 個組慢得多。因此,作者建議要根據目標平臺和任務小心地選擇分組的組數,不能簡單地因爲可以提升準確率就選擇很大的組數,而忽視了因此帶來的巨大計算負擔。

G3:網絡碎片化會減少並行度。

在 Inception 結構中,一般會有多個分支,其中的每一個卷積或者池化操作稱之爲一個碎片操作。這種碎片結構有利於提升準確率,但卻對設備的並行計算不友好,而且也會帶來同步等額外的開銷。因此,作者設計了下面的一系列結構塊,堆疊 10 次組成一個網絡,然後在同等 FLOPs 的情況下測試它們各自的運行速度。

實驗結果如下所示,可以看到在 GPU 上碎片結構會大大降低運算速度,而在 CPU 上則不是那麼明顯。

G4:逐元素的操作不可忽視。

這裏逐元素(Element-wise)的操作包括張量相加,ReLU 等,它們的 FLOPs 很小但卻會有相對較大的 MAC,這裏作者認爲深度卷積也是逐元素的操作,因爲它們的 MAC/FLOPs 比值比較大。

作者採用了 ResNet 的瓶頸結構來實驗,也就是一個 conv 1×1->conv 3×3->conv 1×1 的結構,分別去掉其中的 ReLU 和跳躍連接,然後測試它們各自的運行速度。可以看到無論是去掉其中哪一個操作,運行速度都會加快。

因此,高效的網絡結構應該滿足:1. 使用平衡的卷積,也就是通道數一樣;2. 合理使用分組卷積;3. 減少碎片度;4. 減少逐元素操作。這些在實際中都應該被考慮到而不是僅僅只關注 FLOPs,比如 ShuffleNet V1 嚴重依賴分組卷積,這違反了 G2;MobileNet v2 利用了反轉瓶頸結構,這違反了 G1,而且在通道數較多的擴展層使用 ReLU 和深度卷積,違反了 G4,它是自動生成的結構碎片化很嚴重,這違反了 G3。

4. ShuffleNet V2

ShuffleNet V1 引入了分組點卷積、瓶頸結構和通道打亂,這與上面的指導思想相違背,因此我們要做的就是維持一個較大並且等寬的通道但不利用密集卷積或者太多的分組卷積。

因此作者引入了一個通道分割(channel split)操作,如上圖(c)所示。在每個單元的開始,我們將特徵圖的 cc 個通道分爲兩部分: ccc-c' 個通道和 cc' 個通道,根據 G3 碎片儘可能少,其中一部分保持不變,另一部分包含三個通道數一樣的卷積來滿足 G1。兩個 1×1 的卷積不進行分組一部分是爲了滿足 G2 一部分是因爲通道分割已經分成了兩組。最後,對兩部分的特徵進行拼接,這樣通道數依然保持不變,最後進行一個通道打亂來保證兩部分的信息進行交互。

針對空間下采樣,通道分割被移除,然後輸出通道數變爲兩倍,詳細信息如上圖(d)所示。

上述的基本塊疊加在一起來組成最後的 ShuffleNet V2,其中 c=c/2c'=c/2,在平均池化後還有一個額外的 1×1 的卷積來對特徵進行混合,詳細信息如下表所示。同樣,我們也可以對每一個塊的通道數進行縮放來進一步調整網絡的大小。

ShuffleNet V2 不僅僅非常高效,而且準確率也很高。有兩個主要的原因:一是高效的基本塊可以允許我們的特徵通道數比較多,網絡容量比較大;二是一半的特徵圖直接進入到下一個模塊,這可以看作是一種類似於 DenseNet 和 CondenseNet 的特徵複用。

在 DenseNet 中,作者分析了不同層之間權重的相關性,如下圖左邊所示,可以看到,相鄰層之間的關聯性是遠遠大於其它層的,這也就是說所有層之間的密集連接可能是多餘的。

在 ShuffleNet V2 中,可以證明,第 ii 層和第 i+ji+j 層之間直接相連的特徵圖通道數爲 rjcr^jc,其中 r=(1c)/cr=(1-c')/c。換句話說,特徵複用的數量隨着兩個塊之間的距離是指數級衰減的,如上圖右邊所示。

5. 實驗結果

此外,ShuffleNet V2 的結構也可以用來構建大的模型或者和殘差結構、SE 等相結合具體細節可參考原論文。

獲取更多精彩,請關注「seniusen」!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章