第一部分 設計概述 /Design Introduction
1.1設計目的與應用
隨著人工智能的發展,神經網絡正被逐步應用于智能安防、自動駕駛、醫療等各行各業。目標識別作為人工智能的一項重要應用也擁有著巨大的前景,隨著深度學習的普及和框架的成熟,卷積神經網絡模型的識別精度越來越高。有名的LeNet-5手寫數字識別網絡,精度達到99%,AlexNet模型和VGG-16模型的提出突破了傳統圖像識別算法,GooLeNet和ResNet推動了卷積神經網絡的應用。
但是神經網絡的發展也給我們帶來了更多挑戰,權重參數越來越多,計算量越來越大導致了復雜的模型很難移植到移動端或嵌入式設備中,且嵌入式環境對功耗、實時性、存儲都有著嚴格的約束。因此如何將卷積神經網絡部署到嵌入式設備中是一件非常有意義的事情。目前神經網絡在傳統嵌入式設備上絕大部分是基于ARM平臺,神經網絡在ARM上部署時存在的巨大問題是算力的不足。GPU主要應用于神經網絡訓練階段,對環境和庫的依賴性較大,國內技術積累較弱,難以實現技術自主可控。ASIC 是為特定需求而專門定制優化開發的架構,靈活性較差,缺乏統一的軟硬件開發環境,開發周期長且造價極高所以基于FPGA的硬件加速平臺是時候發揮它的優勢了,FPGA由于獨特的架構被廣泛的應用與實時信號處理、圖像處理領域,其并行性也為卷積神經網絡提供了巨大算力。
傳統的RTL開發FPGA流程相比緩慢,不如軟件的開發效率高,所以HLS運營而生,使用高層次語言來進行轉換為底層的硬件代碼,極大的加快開發進程。因此項目選用HLS工具來實現算法中的加速IP核,將SSD目標檢測網絡移植到FPGA硬件平臺上, 對于硬件加速過程中的算法并行性,在本設計中主要采用兩個方式:對層內的運算并行化,將多個通道的數據進行分塊,每一塊內的通道同時進行運算,最后將結果累加在一起。對于模塊的運算采用HLS并行優化,對數組核循環添加優化指令進行優化。整個系統采用PYNQ的軟件框架來實現,為SSD目標檢測算法提供了硬件加速方案,充分發揮了FPGA的并行性。
1.2 SSD目標檢測算法原理
SSD,Single Shot Multi Box Detector,于2016年提出,是經典的單階段目標檢測模型之一。它的精度可以媲美FasterRcnn雙階段目標檢測方法,速度卻達到了59FPS(512x512,TitanV),單階段目標檢測方法的目標檢測和分類是同時完成的,其主要思路是利用CNN提取特征后,均勻地在圖片的不同位置進行密集抽樣,抽樣時可以采用不同尺度和長寬比,物體分類與預測框的回歸同時進行,整個過程只需要一步,所以其優勢是速度快。
SSD采用的主干網絡是VGG網絡,VGG是由Simonyan 和Zisserman在文獻《Very Deep Convolutional Networks for Large Scale Image Recognition》中提出卷積神經網絡模型,其名稱來源于作者所在的牛津大學視覺幾何組(Visual Geometry Group)的縮寫。該模型參加2014年的 ImageNet圖像分類與定位挑戰賽,取得了優異成績:在分類任務上排名第二,在定位任務上排名第一。
圖1.VGG16網絡結構
這里的VGG網絡相比普通的VGG網絡有一定的修改,主要修改的地方就是:
1、將VGG16的FC6和FC7層轉化為卷積層。
2、去掉所有的Dropout層和FC8層;
3、新增了Conv6、Conv7、Conv8、Conv9。
圖2.SSD主干網絡結構
上圖展示了SSD的主干網絡結構,整個網絡為全卷積網絡結構,SSD將VGG16的兩個全連接層轉換成了普通的卷積層,池化層POOL5由原來的stride=2,kernel大小2x2變成stride=1,kernel大小3x3,為了不改變特征圖大小同時獲得更大的感受野,Conv6改為空洞卷積,diliation=6,輸入的圖片經過了改進的VGG網絡(Conv1->fc7)和幾個另加的卷積層(Conv6->Conv9)進行特征提取。
從圖2我們可以看出,SSD將conv4_3、conv7、conv6_2、conv7_2、conv8_2、conv9_2都連接到了最后的檢測分類層做回歸,6個特征圖分別預測不同大小和長寬比的邊界框,具體細節如圖3。
圖3.SSD特征提取網絡
SSD為每個檢測層都預定義了不同大小的先驗框(prior boxes),Conv4_3、Conv8_2和Conv9_2分別有4個先驗框,而Conv7、conv7_2和Conv8_2分別有6種先驗框,即對應于特征圖上的每個像素,都會生成4或6個prior box.
在淺層的神經網絡里,只能看到圖片的細節和紋理信息,就如管中窺豹。隨著網絡層數的加深,相當于把圖片往后移動一段距離。這樣才能夠感知到圖片的整體信息。低層卷積可以捕捉到更多的細節信息,高層卷積可以捕捉到更多的抽象信息。低層特性更關心“在哪里”,但分類準確度不高,而高層特性更關心“是什么”,但丟失了物體的位置信息。SSD正是利用不同尺度檢測圖片中不同大小和類別的目標物體,獲得了很好的效果。
1.3 作品展示
第二部分 系統組成及功能說明 /System Construction & Function Description
2.1 系統功能
實現了SSD目標檢測網絡在PYNQ平臺上的移植,能夠實現人、自行車、汽車、馬、飛機等20類目標的檢測。輸入任意大小圖像,能夠輸出圖像中所含目標,并輸出目標具體位置。
2.2 系統框圖
系統框圖如下所示:包含卷積模塊、池化模塊、L2范數模塊。CPU控制各個模塊的運行,存取地址,通道數設置等參數,完成整個SSD特征提取網絡,并將各個特征層的數據存儲在DDR內存中,最后CPU對輸出結果進行softmax運算識別出圖片中存在的目標種類,并根據輸出計算出框圖所在的位置。池化模塊和L2范數模塊是通過AXI-Stream數據流的形式對輸入數據進行處理,卷積模塊以M_AXI端口同時讀取特征數據和權重數據。
2.3 模塊劃分
卷積模塊:
為了提高模塊的通用性,對模塊的輸入參數約束為AXI_LITE的端口,方便CPU對模塊進行控制,權重特征及偏置數據連接到3個HP口同時讀取數據。具體的參數如下
設置并行數量K=8時,約束最內層循環II=1,最終得到的資源消耗如下表:
當設置并行數量K=32時,約束最內層循環II=1,消耗的資源如下表:
考慮到硬件的資源,最終選擇了設置K=8路并行處理。
池化模塊:
為了實現流水線的操作,第一步先對輸入特征進行橫向的池化,兩個兩個進行比較,留下較大的那個值,第二步再對縱向池化,縱向池化時需要第一行的值進行緩存,再將第二行的值與其比較,可以使用bram來保存中間值。
L2 范數模塊
根據范數計算的公式,第一步需要對每個通道像素值平方后累加,再開根號。可以將這個計算以流水線的形式對每個通道的像素值進行累加存放到數組中,這個過程同樣可以對多個通道同時操作,增加并行性,等到所有的通道都計算完成后,將所得到的值存入DDR內存地址中,等待下一步使用。
第二步同樣使用流水線的形式取出特征像素和上一步中DDR中存放的數據,進行除法操作,之后再寫回DDR。這樣就完成了整個L2范數流水線的計算。下圖分別為K=16和K=32時消耗資源的對比,可以看出當K變大時,消耗的LUT資源變得很大,在項目中由于該模塊只使用了一次,因此只將K取為8。
2.4 設計優化
并行設計:
為了提高數據的傳輸效率和FPGA的并行特性,我們將特征在內存中的排布方式變為下圖的方式,其中一個長方體子塊代表一個數據子塊,位寬為16*K,K的值可以改變。即每次存取特征數據K個通道的像素值,同時存取K個權重子塊的數據進行運算,
量化設計
因為FPGA并不比擅長對浮點數進行運算,如果特征和權重數據都使用浮點數則會導致資源的消耗特別厲害,因此為了解決這個問題,采用定點數的形式對所有的數據進行定點化處理。為了獲取權重及特征的小數精度,要對訓練好的權重數據進行統計,對于不同層的權重使用不同精度的定點數,同時要在前向網絡時對數據集中所有數據進行統計,獲取每一層特征數據的精度范圍,將這些精度保留作為卷積模塊的輸入參數。在所有模塊中的計算都是直接使用定點數進行運算。
下圖為提取的部分權重小數點精度和偏置小數點精度,可以發現大部分小數點的位數都很高。所以只需要很少的比特去表示整數位。
2.5 Python 網絡搭建
第一步.通過PYNQ調用卷積和池化單元完成主干特征網絡的實現
#layer 1
Run_Conv(conv,3,64,3,3,1,1,1,1,0,image,0,vgg1_1w,15,vgg1_1b,14,vgg1_1,5)
Run_Conv(conv,64,64,3,3,1,1,1,1,0,vgg1_1,5,vgg1_2w,15,vgg1_2b,15,vgg1_2,3)
Run_Pool(pool,dma,64,2,2,vgg1_2,vgg1_p)
#layer 2
Run_Conv(conv,64,128,3,3,1,1,1,1,0,vgg1_p,3,vgg2_1w,15,vgg2_1b,15,vgg2_1,2)
Run_Conv(conv,128,128,3,3,1,1,1,1,0,vgg2_1,2,vgg2_2w,15,vgg2_2b,15,vgg2_2,2)
Run_Pool(pool,dma,128,2,2,vgg2_2,vgg2_p)
#layer 3
Run_Conv(conv,128,256,3,3,1,1,1,1,0,vgg2_p,2,vgg3_1w,15,vgg3_1b,15,vgg3_1,2)
Run_Conv(conv,256,256,3,3,1,1,1,1,0,vgg3_1,2,vgg3_2w,15,vgg3_2b,15,vgg3_2,2)
Run_Conv(conv,256,256,3,3,1,1,1,1,0,vgg3_2,2,vgg3_3w,15,vgg3_3b,15,vgg3_3,2)
Run_Pool(pool,dma,256,2,2,vgg3_3,vgg3_cp)
#layer 4
Run_Conv(conv,256,512,3,3,1,1,1,1,0,vgg3_cp,2,vgg4_1w,15,vgg4_1b,15,vgg4_1,2)
Run_Conv(conv,512,512,3,3,1,1,1,1,0,vgg4_1,2,vgg4_2w,15,vgg4_2b,15,vgg4_2,4)
Run_Conv(conv,512,512,3,3,1,1,1,1,0,vgg4_2,4,vgg4_3w,15,vgg4_3b,15,vgg4_3,5)
Run_Pool(pool,dma,512,2,2,vgg4_3,vgg4_p)
#layer 5
Run_Conv(conv,512,512,3,3,1,1,1,1,0,vgg4_p,5,vgg5_1w,15,vgg5_1b,15,vgg5_1,6)
Run_Conv(conv,512,512,3,3,1,1,1,1,0,vgg5_1,6,vgg5_2w,15,vgg5_2b,15,vgg5_2,7)
Run_Conv(conv,512,512,3,3,1,1,1,1,0,vgg5_2,7,vgg5_3w,15,vgg5_3b,12,vgg5_3,7)
Run_Pool_Soft_padding(512,3,3,vgg5_3,vgg5_p)
#exter 1 dilation
Run_Conv(conv,512,1024,3,3,1,1,1,1,1,vgg5_p,7,ex1_1w,15,ex1_1b,15,ex1_1,9)
Run_Conv(conv,1024,1024,1,1,1,1,0,1,0,ex1_1,9,ex1_2w,15,ex1_2b,15,ex1_2,11)
#exter 2
Run_Conv(conv,1024,256,1,1,1,1,0,1,0,ex1_2,11,ex2_1w,15,ex2_1b,15,ex2_1,12)
Run_Conv(conv,256,512,3,3,2,2,1,1,0,ex2_1,12,ex2_2w,15,ex2_2b,15,ex2_2,11)
#exter 3
Run_Conv(conv,512,128,1,1,1,1,0,1,0,ex2_2,11,ex3_1w,15,ex3_1b,15,ex3_1,11)
Run_Conv(conv,128,256,3,3,2,2,1,1,0,ex3_1,11,ex3_2w,15,ex3_2b,15,ex3_2,10)
#exter 4
Run_Conv(conv,256,128,1,1,1,1,0,1,0,ex3_2,10,ex4_1w,15,ex4_1b,15,ex4_1,10)
Run_Conv(conv,128,256,3,3,1,1,0,1,0,ex4_1,10,ex4_2w,15,ex4_2b,15,ex4_2,10)
#exter 5
Run_Conv(conv,256,128,1,1,1,1,0,1,0,ex4_2,10,ex5_1w,15,ex5_1b,15,ex5_1,10)
Run_Conv(conv,128,256,3,3,1,1,0,1,0,ex5_1,10,ex5_2w,15,ex5_2b,15,ex5_2,9)
第二步.對特定檢測層卷積得到分類預測和回歸預測數據
#Loc
Run_Conv(conv,1024,24,3,3,1,1,1,0,0,ex1_2,11,l2,15,l2b,15,L2,12)
Run_Conv(conv,512,24,3,3,1,1,1,0,0,ex2_2,11,l3,15,l3b,15,L3,12)
Run_Conv(conv,256,24,3,3,1,1,1,0,0,ex3_2,10,l4,15,l4b,15,L4,12)
Run_Conv(conv,256,16,3,3,1,1,1,0,0,ex4_2,10,l5,15,l5b,15,L5,12)
Run_Conv(conv,256,16,3,3,1,1,1,0,0,ex5_2,9,l6,15,l6b,15,L6,12)
#Conf
Run_Conv(conv,1024,126,3,3,1,1,1,0,0,ex1_2,11,c2,15,c2b,15,C2,10)
Run_Conv(conv,512,126,3,3,1,1,1,0,0,ex2_2,11,c3,15,c3b,15,C3,10)
Run_Conv(conv,256,126,3,3,1,1,1,0,0,ex3_2,10,c4,15,c4b,15,C4,10)
Run_Conv(conv,256,84,3,3,1,1,1,0,0,ex4_2,10,c5,15,c5b,15,C5,10)
Run_Conv(conv,256,84,3,3,1,1,1,0,0,ex5_2,9,c6,15,c6b,15,C6,10)
第三部分 完成情況及性能參數 /Final Design & Performance Parameters
(作品已實現的功能及性能指標)
目前作品在功能上已經完成了所預定的功能:實現SSD目標檢測網絡在PYNQ上的部署,能夠做到輸入一幅圖像,輸出圖中的目標,并找到目標所在的位置。
因為對特征權重數據使用了量化的方法,大幅度減少了資源的消耗。下圖對比了將部分輸入參數改為int類型后消耗的資源情況,可以看到消耗的DSP資源是定點數的一倍多。
雖然項目達到了部分預期的效果,但也存在著一些問題,目前雖然對FPGA模塊設計了并行計算,但是工作時鐘頻率卻沒有達到預期的100MHz,只使用了50MHz,計算一幅圖像需要花費好幾分鐘的時間。下一步的工作希望能夠繼續學習如何能夠提高HLS電路的工作頻率,同時進一步提高數據并行的數量,以此來提高目標檢測的速度。
-
FPGA
+關注
關注
1645文章
22034瀏覽量
617880 -
神經網絡
+關注
關注
42文章
4814瀏覽量
103480 -
目標檢測
+關注
關注
0文章
224瀏覽量
15999
原文標題:基于 FPGA 及神經網絡SSD算法目標檢測系統設計
文章出處:【微信號:HXSLH1010101010,微信公眾號:FPGA技術江湖】歡迎添加關注!文章轉載請注明出處。
發布評論請先 登錄
PowerPC小目標檢測算法怎么實現?
基于YOLOX目標檢測算法的改進
基于SSD網絡模型的多目標檢測算法
基于多尺度融合SSD的小目標檢測算法綜述
基于Grad-CAM與KL損失的SSD目標檢測算法
淺談紅外弱小目標檢測算法
基于強化學習的目標檢測算法案例
基于Transformer的目標檢測算法

評論