出品 | 智東西公開課
講師 | 童志軍 閲面科技合夥人&CTO
嵌入式04,即可獲取課件。
導讀:
4月17日,閲面科技合夥人&CTO童志軍在智東西公開課進行了嵌入式AI合輯第四講的直播講解,主題為《面向嵌入式設備的輕量級神經網絡模型設計》。
在本次講解中,童志軍老師從神經網絡模型在嵌入式設備運行的挑戰、神經網絡模型從“特徵驅動”、“數據驅動”、“精度優先”到“速度優先”等不同階段的發展歷程,並通過實際案例解讀如何在嵌入式設備上實現神經網絡模型的高效部署和運行。
本文為此次課程主講環節的圖文整理:
正文:
大家好,我是閲面科技合夥人&CTO童志軍,很高興能在智東西公開課和大家一起分享今天的課題。我今天分享的主題為《面向嵌入式設備的輕量級神經網絡模型設計》,主要分為以下4個部分:
1、神經網絡模型在嵌入式設備運行的挑戰
2、從“特徵驅動”到“數據驅動”的大型神經網絡模型設計
3、從“精度優先”到“速度優先”的輕量級神經網絡模型設計
4、在嵌入式設備實現神經網絡模型的高效部署與運行
神經網絡模型在嵌入式設備運行的挑戰
目前,在所看見的嵌入式設備上,很大一部分會有AI的算法的身影。在我們身邊也有很多應用,比如刷臉解鎖手機、刷臉支付、家用的攝像頭,或馬路上隨處可見的公共安防攝像頭等。
嵌入式設備在我們身邊無孔不入,這些設備分為兩種,一種是隻做視頻的抓取沒有計算,只是把視頻傳到後台服務器,然後做分析;另一種是設備上會帶有AI計算能力,一些算法會在前端設備上去計算,然後把計算得到的結構化數據再傳到後端服務器去做進一步分析。
上圖左邊列舉了一些主流的神經網絡模型,包括計算量及參數量,相應在Imagenet公開數據集上Top-1的精度。上圖橫座標代表的是計算的浮點計算量,然後縱座標是精度。可以看到神經網絡模型的精度與模型的計算量成正比,隨着模型計算量越來越大,精度也越來越高。
但也可以看到,網絡模型的精度與模型的參數量是沒有完全呈正比。比如VGG網絡,它的參數量很大,但是精度不是特別高。在嵌式設備上運行神經網絡,首先要求模型的精度要非常高,只有模型的精度達到一定的準確率才能滿足人們實際使用的需求。由於嵌入式設備的功耗、存儲及計算資源都非常有限,如何在有限的計算資源下把高精度的模型運行為實時動態的效果是非常重要的,這裏會涉及到算法、算力及數據幾個層面的優化,今天主要與大家探討在算法層面,更確切的是在網絡設計的層面如何解決?
從“特徵驅動”到“數據驅動”的大型神經網絡模型設計
首先回顧下大型的神經網絡模型的發展脈絡,其實卷積神經網絡很早就出現, LeNet-5很早在美國郵政的數字識別上已經得到很好的應用。但後來並沒有得到更多的推廣,沉默了10年,10年內主流的一些視覺分析的方法還是手工特徵。
對於手工特徵,大家比較熟悉的是SIFT特徵,它是在x方向跟y方向去提取梯度圖,然後把每一個像素的梯度圖按照一定的角度區間各自去做梯度方向的投影,最終得到128位的描述子。如果把這個問題換一個角度來思考,可以發現 SIFT特徵的生成過程,可以等效是一個卷積層和一個pooling層。
上圖可以看到它的8個方向的梯度,代表的是輸出Channel為8,kernel大小為1*1的卷積,輸入是x方向跟y方向的梯度流。對於 x方向跟y方向的圖,等效成一個2*8*1*1的卷積操作,後面再接了一個8*8*4*4的Pooling層,最終得到一個兩層的神經網絡結構。
隨着特徵描述的發展,逐漸從底層的特徵設計發展到中層特徵設計。中層特徵設計比較典型的是Fisher Vector,它在圖像搜索的方面應用的非常廣泛。Fisher Vector特徵首先對圖像做特徵提取,然後基於GMM模型對特徵做進一步的編碼,編碼得到的特徵,再通過空間卷積得到在不同的尺度空間上的特徵描述。用現在的神經網絡結構的方式去看,可以等效為一個SIFT特徵提取過程,加一個編碼層和一個Pooling層,即為一個四層的神經網絡結構。4層的網神經網絡結構比兩層的神經網絡精度會更高,特徵也更抽象,表達能力更強。
到2010年時,李飛飛教授帶領的一幫學者整理了一個非常大型的數據集-Imagenet,這個數據集有1000類,大概120萬張圖片,這個數據集的出現是神經網絡得到飛速發展的基石,掀起了整個AI界的軍備競賽。
時間到了2012年,ImageNet比賽冠軍提出來一個新的網絡AlexNet。它由5個卷積層,3個全連接層。另外由於當時GPU顯存的限制,把網絡的卷積分成分組的形式,使得網絡能夠在 GPU有限的情況下運行起來,裏面還有drop out的技巧等。AlexNet開創了神經網絡結構的一個新河,在此之後,工業界的人開始相信深度學習是有效的,可以產生一些有價值的東西,而不僅是學術界的一個玩具。
2014年,出現了VGG和GoogleNet兩種不同的網絡結構,兩個網絡其實都是在不同層面對網絡去建模。在早期,AlexNet出現之後,在調網絡的時候發現一種很奇怪的現象,當把層數往上堆時,很容易出現梯度彌散的效應。如何把網絡做深,在當時一直沒有得到很好的解決。
VGG跟GoogleNet做的網絡都接近20層左右,這是一個突破,這裏也是使用了一些技巧,比如 GoogleNet是在層中間插入 loss的監督, 然後在block的設計上引入了一些技巧,通過這種多尺度的卷積核,提取圖像上的多尺度的信息。其實尺度是一個非常重要的因素。另外逐層的 finetuning,在VGG用的比較多,還引入了連續兩個3×3的卷積核去模擬5×5的感受野,它使得網絡可以做得更深,精度做得更高。
2015年,微軟亞洲研究員何凱明設計的殘差網絡,把神經網絡從20層提升到幾百層。可以看到網絡層數越來越深,而且網絡的寬度也越來越寬,當然最終的精度也是非常高。
上圖為ImageNet分類Top5錯誤率圖,可以看到網絡的精度隨着層數逐漸增加越來越高,網絡結構也在不斷創新。
從“精度優先”到“速度優先”的輕量級神經網絡模型設計
自2015-2016年之後出現網絡模型有往端上發展的趨勢,如何把神經網絡模型在終端上跑得更快,是演變的一個趨勢,也就是模型的設計從精度優先到後來的速度優先。
我們可以簡單分析下神經網絡模型的計算量,可以看到一般的神經網絡模型,大部分都是由卷積層組成,卷積層在裏面的計算量佔到了80%以上,卷積的計算示意圖如上圖所示,計算複雜度為N*M*H*W*K*K。
輕量級的神經網絡模型所做的工作,就是圍繞着計算複雜度,把裏面的一些參數儘量的減小,使得計算量能夠降低。計算量在嵌入式設備上體現最明顯的是它的速度。如何在優化計算複雜度的同時保證模型的高精度,就是下面一些主流的神經網絡模型設計所做的工作。
最開始比較有代表性的一個網絡是SqueezeNet網絡,它有兩個特點,先用1×1的卷積核做通道壓縮,然後把1×1與3×3的卷積核並排,使得卷積核可以更小。也就是通過減小通道數以及卷積核大小降低模型的計算量,使得模型可以推理的更快。
第二個是MobileNet網絡和ShuffleNet網絡,MobileNet網絡用到一個比較重要的點是Depthwise卷積,也是把原來稠密的卷積N*M的計算量,直接優化為N的計算量。ShuffleNet網絡借鑑了 MobileNet網絡一些點,比如Depthwise卷積,當應用Depthwise卷積後,發現整個神經網絡計算量更多是在1×1的卷積上,這時就可以把1×1卷積去做一個通道Shuffle分組,分組之後做通道卷積,使得它能夠在3×3上再進一步的融合,可以看到大家更多的是把卷積由原來的稠密卷積變成通道的卷積。
最近的神經網絡是模型搜索NAS,這方面有很多的輕量級的網絡結構,但是沒有把它應用到嵌入設備上,為什麼?因為 NAS搜索出來的網絡規律性比較差,對嵌入式設備不是很友好。實際應用更多的還是停留在MobileNet網絡這種比較直線型的網絡上去優化。
後來有一個EfficientNet網絡結構,它的想法比較綜合,把網絡計算量的幾個因素同時去做一個聯合搜索優化,比如網絡的層數,或者圖像的feature map的長寬,以及計算複雜度中提到的N、M、K,去做一個統一的建模,通過增強學習去搜索最優解。另外,網絡結構也做一些重複的堆疊,相對非常有規律,對整個嵌入式設備還是非常友好的。
在嵌入式設備實現神經網絡模型的高效部署與運行
首先看下整體的加速框架,這裏面大概包含了閲面所做的一些工作,左邊是訓練端,主要做了模型的通道剪枝、模型蒸餾和量化訓練的工作,右邊是在嵌入式設備上做模型的轉換,以及卷積運算算子的優化,使得我們的模型可以在一些硬件層面快速的跑起來。
第一個是通道剪枝,剪枝包括稀疏化等,但對嵌入式設備不是很友好,因為稀疏化剪枝得到的模型沒有規律,讓內存的取值變得隨機,使得設備速度跑不起來。後來通道剪枝可以得到規則模型,使得剪完之後的模型能夠複用以前的計算引擎,這方面更多的是基於一些規則,比如選取響應最大卷積核或選一些方差比較大的卷積核,對卷積核建模,通道壓縮率也可以通過強化學習的方法去反覆搜索,最終得到最優的結果。
通道剪枝主要針對MobileNetV2和 EfficientNet這類網絡,可以看到當模型從原來的200-300M的計算規模,到後來100M以下,其精度下降在一個可以接受的範圍內,這樣的模型可以在檢測或者是識別任務上得到很好的使用。
第二是模型蒸餾,最早主要是體現在loss設計上,比如 Student模型去學習Teacher模型的樣本分佈,最終來提高Student模型的精度。以Margin為例,Margin在細粒度分類上用的比較多。通過Student模型去學習Teacher模型的Margin分佈,使得Student模型的精度得到非常大的提升。
上圖為訓練人臉識別網絡,第一行是 Teacher模型的精度,第二行是Student模型的一個baseline ,第三行是用模型蒸餾的方法產生的Student模型的記錄,可以看到訓練出的 Student模型的精度,是介於Teacher模型跟Student模型之間,而且比較接近Teacher模型的精度,相對於baseline有非常大的提升。
第三塊是量化訓練,為什麼要做量化訓練?模型量化會帶來很多好處,最常見的比如可以把模型的存儲量,從原來的FP32減到INT16或INT8,直接減掉一半或1/4。另一點是做量化之後,使得模型做並行加速,比如同樣一個指令週期,原來可以操作1個浮點數,現在可以同時操作2個INT16或4個INT8,使得數據的吞吐量提升,這也是一種提速。
它的流程如下:首先會收集前向的數據集,然後對網絡做統計,統計分為兩部分,一個是模型的 weight做最大最小或者 kr散度分佈上的統計,另一個是對模型的輸入輸出做統計,從而可以選取到最優的一個標準去對模型做量化。如果只做INT16的量化,模型的精度是可以完全保持住的。但當做更低精度,比如INT8或INT4,模型精度會有一些損失,這時還需要做一些finetune,使得模型精度可以回到跟原來浮點模型的精度。
上圖是在人臉識別模型上所做的工作,比如FP32在1/10萬是達到97.94%的識別率,直接量化INT8,精度為 85.17,通過finetune使得最終的模型可能只降低了1~2個點。量化是一個非常有效的降低模型計算量,同時適合嵌入式設備,不管是功耗或存儲的佔用都非常友好。
第四點是當得到一個最優的模型結構之後,最終部署到嵌入式設備上,就涉及到推理引擎。推薦引擎主要的計算在卷積運算, 我們採用的是直接基於原始的卷積方式做優化。這涉及到行主序的內存重排、矩陣分塊、內存對齊、內存複用、緩存預讀取、SIMD並行加速、循環展開、多線程等。
我們在RK3288上做的優化,對比的是騰訊開源的NCNN推理引擎。可以看到在同樣的輸入下,我們的速度提升大概有40%~50%之間,這個引擎還在持續的優化,算子的計算優化也是非常重要的一環。
最後總結下,在嵌入式模型部署所做的工作,首先會得到檢測或識別的業務模型,根據具體客户的需求訓練浮點模型,之後做模型蒸餾的loss訓練,把計算量做進一步的精簡。精簡完之後,對一些稀疏的通道,做進一步的剪枝,並且把模型finetune,得到一個最緊湊的深度學習模型。之後根據前面的一些積累,我們更多是基於Caffe的框架,在這個基礎之上對模型做進一步的量化,量化可能會根據具體硬件不同會有所不同。最終得到一個最優化的量化模型之後,把算子計算庫打包一起,最終形成一個運行程序,部署到實際的設備上。上面就是完整的模型部署的流程。
以上就是我今天的分享內容,謝謝大家。