輕量級(jí)卷積神經(jīng)網(wǎng)絡(luò)的設(shè)計(jì)技巧

這篇文章將從一個(gè)證件檢測(cè)網(wǎng)絡(luò)(Retinanet)的輕量化談起,簡(jiǎn)潔地介紹,我在實(shí)操中使用到的設(shè)計(jì)原則和idea,并貼出相關(guān)的參考資料和成果供讀者參考。因此本文是一篇注重工程性、總結(jié)個(gè)人觀點(diǎn)的文章,存在不恰當(dāng)?shù)牡胤剑?qǐng)讀者在評(píng)論區(qū)指出,方便交流。
目前已有的輕量網(wǎng)絡(luò)有:MobileNet V2和ShuffleNet v2為代表。在實(shí)際業(yè)務(wù)中,Retinanet僅需要檢測(cè)證件,不涉及過(guò)多的類(lèi)別物體的定位和分類(lèi),因此,我認(rèn)為僅僅更換上述兩個(gè)骨架網(wǎng)絡(luò)來(lái)優(yōu)化模型的性能是不夠的,需要針對(duì)證件檢測(cè)任務(wù),專(zhuān)門(mén)設(shè)計(jì)一個(gè)更加輕量的卷積神經(jīng)網(wǎng)絡(luò)來(lái)提取、糅合特征。
設(shè)計(jì)原則:
1. 更多的數(shù)據(jù)
輕量的淺層網(wǎng)絡(luò)特征提取能力不如深度網(wǎng)絡(luò),訓(xùn)練也更需要技巧。假設(shè)保證有足夠多的訓(xùn)練的數(shù)據(jù),輕量網(wǎng)絡(luò)訓(xùn)練會(huì)更加容易。
Facebook研究院的一篇論文[1]提出了“數(shù)據(jù)蒸餾”的方法。實(shí)際上,標(biāo)注數(shù)據(jù)相對(duì)未知數(shù)據(jù)較少,我使用已經(jīng)訓(xùn)練好、效果達(dá)標(biāo)的base resnet50的retinanet來(lái)進(jìn)行自動(dòng)標(biāo)注,得到一批10萬(wàn)張機(jī)器標(biāo)注的數(shù)據(jù)。這為后來(lái)的輕量網(wǎng)絡(luò)設(shè)計(jì)奠定了數(shù)據(jù)基礎(chǔ)。我認(rèn)為這是構(gòu)建一個(gè)輕量網(wǎng)絡(luò)必要的條件之一,網(wǎng)絡(luò)結(jié)構(gòu)的有效性驗(yàn)證離不開(kāi)大量的實(shí)驗(yàn)結(jié)果來(lái)評(píng)估。
接下來(lái),這一部分我將簡(jiǎn)潔地介紹輕量CNN地設(shè)計(jì)的四個(gè)原則
2. 卷積層的輸入、輸出channels數(shù)目相同時(shí),計(jì)算需要的MAC(memory access cost)最少

3. 過(guò)多的分組卷積會(huì)增加MAC
對(duì)于1x1的分組卷積(例如:MobileNetv2的深度可分離卷積采用了分組卷積),其MAC和FLOPS的關(guān)系為:

g代表分組卷積數(shù)量,很明顯g越大,MAC越大。詳細(xì)參考[2]
4. 網(wǎng)絡(luò)結(jié)構(gòu)的碎片化會(huì)減少可并行計(jì)算
這些碎片化更多是指網(wǎng)絡(luò)中的多路徑連接,類(lèi)似于short-cut,bottle neck等不同層特征融合,還有如FPN。拖慢并行的一個(gè)很主要因素是,運(yùn)算快的模塊總是要等待運(yùn)算慢的模塊執(zhí)行完畢。

5. Element-wise操作會(huì)消耗較多的時(shí)間(也就是逐元素操作)
從表中第一行數(shù)據(jù)看出,當(dāng)移除了ReLU和short-cut,大約提升了20%的速度。

以上是從此篇論文[2]中轉(zhuǎn)譯過(guò)來(lái)的設(shè)計(jì)原則,在實(shí)操中,這四條原則需要靈活使用。
根據(jù)以上幾個(gè)原則進(jìn)行網(wǎng)絡(luò)的設(shè)計(jì),可以將模型的參數(shù)量、訪存量降低很大一部分。
接下來(lái)介紹一些自己總結(jié)的經(jīng)驗(yàn)。
6. 網(wǎng)絡(luò)的層數(shù)不宜過(guò)多
通常18層的網(wǎng)絡(luò)屬于深層網(wǎng)絡(luò),在設(shè)計(jì)時(shí),應(yīng)選擇一個(gè)參考網(wǎng)絡(luò)基線,我選擇的是resnet18。由于Retinanet使用了FPN特征金字塔網(wǎng)絡(luò)來(lái)融合各個(gè)不同尺度范圍的特征,因此Retinanet仍然很“重”,需要盡可能壓縮骨架網(wǎng)絡(luò)的冗余,減少深度。
7. 首層卷積層用空洞卷積和深度可分離卷積替換
一個(gè)3x3,d=2的空洞卷積在感受野上,可以看作等效于5x5的卷積,提供比普通3x3的卷積更大的感受野,這在網(wǎng)絡(luò)的淺層設(shè)計(jì)使用它有益。計(jì)算出網(wǎng)絡(luò)各個(gè)層占有的MAC和參數(shù)量,將參數(shù)量和計(jì)算量“重”的卷積層替換成深度可分離卷積層,可以降低模型的參數(shù)量。
這里提供一個(gè)計(jì)算pytorch 模型的MAC和FLOPs的python packages[3]。
if __name__ == "__main__":
from ptflops import get_model_complexity_info
net = SNet(num_classes=1)
x = torch.Tensor(1, 3, 224, 224)
net.eval()
if torch.cuda.is_available():
net = net.cuda()
x = x.cuda()
with torch.cuda.device(0):
flops, params = get_model_complexity_info(net, (224, 224), print_per_layer_stat=True, as_strings=True, is_cuda=True)
print("FLOPS:", flops)
print("PARAMS:", params)
output:
(regressionModel): RegressionModel(
0.045 GMac, 27.305% MACs,
(conv1): Conv2d(0.009 GMac, 5.257% MACs, 128, 256, kernel_size=(1, 1), stride=(1, 1))
(act1): ReLU(0.0 GMac, 0.041% MACs, )
(conv2): Conv2d(0.017 GMac, 10.472% MACs, 256, 256, kernel_size=(1, 1), stride=(1, 1))
(act2): ReLU(0.0 GMac, 0.041% MACs, )
(conv3): Conv2d(0.017 GMac, 10.472% MACs, 256, 256, kernel_size=(1, 1), stride=(1, 1))
(act3): ReLU(0.0 GMac, 0.041% MACs, )
(output): Conv2d(0.002 GMac, 0.982% MACs, 256, 24, kernel_size=(1, 1), stride=(1, 1))
)
(classificationModel): ClassificationModel(
0.044 GMac, 26.569% MACs,
(conv1): Conv2d(0.009 GMac, 5.257% MACs, 128, 256, kernel_size=(1, 1), stride=(1, 1))
(act1): ReLU(0.0 GMac, 0.041% MACs, )
(conv2): Conv2d(0.017 GMac, 10.472% MACs, 256, 256, kernel_size=(1, 1), stride=(1, 1))
(act2): ReLU(0.0 GMac, 0.041% MACs, )
(conv3): Conv2d(0.017 GMac, 10.472% MACs, 256, 256, kernel_size=(1, 1), stride=(1, 1))
(act3): ReLU(0.0 GMac, 0.041% MACs, )
(output): Conv2d(0.0 GMac, 0.245% MACs, 256, 6, kernel_size=(1, 1), stride=(1, 1))
(output_act): Sigmoid(0.0 GMac, 0.000% MACs, )
)8. Group Normalization 替換 Batch Normalization
BN在諸多論文中已經(jīng)被證明了一些缺陷,而訓(xùn)練目標(biāo)檢測(cè)網(wǎng)絡(luò)耗費(fèi)顯存,開(kāi)銷(xiāo)巨大,通常凍結(jié)BN來(lái)訓(xùn)練,原因是小批次會(huì)讓BN失效,影響訓(xùn)練的穩(wěn)定性。建議一個(gè)BN的替代--GN,pytorch 0.4.1內(nèi)置了GN的支持。
9. 減少不必要的shortcut連接和RELU層
網(wǎng)絡(luò)不夠深,沒(méi)有必要使用shortcut連接,不必要的shortcut會(huì)增加計(jì)算量。RELU與shortcut一樣都會(huì)增加計(jì)算量。同樣RELU沒(méi)有必要每一個(gè)卷積后連接(需要實(shí)際訓(xùn)練考慮刪減RELU)。
10. 善用1x1卷積
1x1卷積可以改變通道數(shù),而不改變特征圖的空間分辨率,參數(shù)量低,計(jì)算效率也高。如使用kernel size=3,stride=1,padding=1,可以保證特征圖的空間分辨率不變,1x1的卷積設(shè)置stride=1,padding=0達(dá)到相同的目的,而且1x1卷積運(yùn)算的效率目前有很多底層算法支持,效率更高。[5x1] x [1x5] 兩個(gè)卷積可以替換5x5卷積,同樣可以減少模型參數(shù)。
11. 降低通道數(shù)
降低通道數(shù)可以減少特征圖的輸出大小,顯存占用量下降明顯。參考原則2
12. 設(shè)計(jì)一個(gè)新的骨架網(wǎng)絡(luò)找對(duì)參考網(wǎng)絡(luò)
一個(gè)好的骨架網(wǎng)絡(luò)需要大量的實(shí)驗(yàn)來(lái)支撐它的驗(yàn)證,因此在工程上,參考一些實(shí)時(shí)網(wǎng)絡(luò)結(jié)構(gòu)設(shè)計(jì)自己的骨架網(wǎng)絡(luò),事半功倍。我在實(shí)踐中,參考了這篇[4]paper的骨架來(lái)設(shè)計(jì)自己的輕量網(wǎng)絡(luò)。
總結(jié)
我根據(jù)以上的原則和經(jīng)驗(yàn)對(duì)Retinanet進(jìn)行瘦身,不僅局限于骨架的新設(shè)計(jì),F(xiàn)PN支路瘦身,兩個(gè)子網(wǎng)絡(luò)(回歸網(wǎng)絡(luò)和分類(lèi)網(wǎng)絡(luò))均進(jìn)行了修改,期望性能指標(biāo)FPS提升到63,增幅180%。
FPS

mAP

Model size

好消息!
小白學(xué)視覺(jué)知識(shí)星球
開(kāi)始面向外開(kāi)放啦??????
下載1:OpenCV-Contrib擴(kuò)展模塊中文版教程 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):擴(kuò)展模塊中文教程,即可下載全網(wǎng)第一份OpenCV擴(kuò)展模塊教程中文版,涵蓋擴(kuò)展模塊安裝、SFM算法、立體視覺(jué)、目標(biāo)跟蹤、生物視覺(jué)、超分辨率處理等二十多章內(nèi)容。 下載2:Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目52講 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):Python視覺(jué)實(shí)戰(zhàn)項(xiàng)目,即可下載包括圖像分割、口罩檢測(cè)、車(chē)道線檢測(cè)、車(chē)輛計(jì)數(shù)、添加眼線、車(chē)牌識(shí)別、字符識(shí)別、情緒檢測(cè)、文本內(nèi)容提取、面部識(shí)別等31個(gè)視覺(jué)實(shí)戰(zhàn)項(xiàng)目,助力快速學(xué)校計(jì)算機(jī)視覺(jué)。 下載3:OpenCV實(shí)戰(zhàn)項(xiàng)目20講 在「小白學(xué)視覺(jué)」公眾號(hào)后臺(tái)回復(fù):OpenCV實(shí)戰(zhàn)項(xiàng)目20講,即可下載含有20個(gè)基于OpenCV實(shí)現(xiàn)20個(gè)實(shí)戰(zhàn)項(xiàng)目,實(shí)現(xiàn)OpenCV學(xué)習(xí)進(jìn)階。 交流群
歡迎加入公眾號(hào)讀者群一起和同行交流,目前有SLAM、三維視覺(jué)、傳感器、自動(dòng)駕駛、計(jì)算攝影、檢測(cè)、分割、識(shí)別、醫(yī)學(xué)影像、GAN、算法競(jìng)賽等微信群(以后會(huì)逐漸細(xì)分),請(qǐng)掃描下面微信號(hào)加群,備注:”昵稱(chēng)+學(xué)校/公司+研究方向“,例如:”張三 + 上海交大 + 視覺(jué)SLAM“。請(qǐng)按照格式備注,否則不予通過(guò)。添加成功后會(huì)根據(jù)研究方向邀請(qǐng)進(jìn)入相關(guān)微信群。請(qǐng)勿在群內(nèi)發(fā)送廣告,否則會(huì)請(qǐng)出群,謝謝理解~
