RM新时代网站-首页

電子發(fā)燒友App

硬聲App

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示
創(chuàng)作
電子發(fā)燒友網>電子資料下載>電子資料>Maix-EMC深度學習模型的嵌入式部署

Maix-EMC深度學習模型的嵌入式部署

2022-04-14 | zip | 27.86 MB | 次下載 | 2積分

資料介紹

授權協議 Apache
開發(fā)語言 Python
軟件類型 開源軟件
所屬分類 其他開源、 開源硬件

軟件簡介

深度學習模型的嵌入式部署一直以來都不是那么得容易,雖然現在有Nvidia Nano和TFLite的樹莓派部署,但要么硬件成本太高、功耗太大、要么性能太差,難以實用化和產品化。一方面,AI科學家和工程師沒有太多的嵌入式知識,另一方面,嵌入式工程師沒有太多AI的知識,因此很需要開源硬件社區(qū)來解決這些問題。

本文介紹AIoT目前的情況以及面臨的挑戰(zhàn),并講解Maix-EMC的開發(fā)緣由,功能和實現。我們也希望有一定基礎的小伙伴可以加入開源社區(qū)一起完善Maix-EMC,讓大家可以轉換更多結構的模型到低成本AIoT硬件上。(參與項目貢獻的小伙伴可獲贈Maix套裝一份?。?/p>

眼瞅著AI紅紅火火,無數的嵌入式工程師也眼紅著。與此同時,一大批AI科學家開發(fā)出來的模型,也面臨落地問題。基于安卓或者Linux開發(fā)者還好,谷歌大佬給了TFLite的支持,但是沒有AI加速器的普通ARM平臺板子成本動輒已經幾百元了,而跑起模型來卻只有幾幀。。玩單片機的嵌入式工程師手頭的主控芯片往往算力最高僅數百MOPS,內存數百KB,也沒有TFLite解釋器,一切都是那么絕望。

?

OpenMV模組

另一方面,AI科學家和工程師們也有著自己的硬件夢,估計很多人早就用樹莓派玩起了TFLite,或者更深入地玩起了Tengine, NCNN等加速引擎。但是沒有AI加速器的加持,再怎么優(yōu)化,幀數還是個位數,價格親民的樹莓派3+攝像頭 成本也要接近300元了!

?

樹莓派開發(fā)板


作為嵌入式設備主控芯片的老大哥---ARM,早早地出了在自家Cortex-M系列芯片上運行的NN后端支持庫:CMSIS-NN。然而其充其量相當于TF的ops的底層實現,需要用戶小心翼翼地管理內存,設置量化參數。這都2019年了,誰還想要像5000年前那樣手工擼神經網絡呢?


2019年,谷歌也推出了TFLite for Micro,與ARM相反,谷歌是從復雜的TFLite往下精簡。粗粗翻閱TFLite for Micro的代碼,目前還在比較初級的階段,支持的ops比較少,內存管理貌似不夠精簡(使用了大量的allocator),為了支持一些動態(tài)特性有些許效率的犧牲。當然其優(yōu)點還是支持從谷歌的TFLite轉換。

目前,這兩者都還處于實驗階段,還沒有跑起來MobileNet等大家耳熟能詳的輕量級網絡,能跑的只是MNIST或者Cifar10等級的教學意義上的小網絡,沒有任何的意義,并且它們對要求使用者具有豐富的神經網絡經驗,包括但不限于:量化,剪枝,蒸餾,壓縮。這些都大大限制了它的實用性。

不過,高手在民間,2019年春節(jié),在UP主的QQ群里就活捉了一只來自拉夫堡大學的生猛老博,他的嵌入式神經網絡框架NNoM就實現了不錯的可用性,讓用戶可以忽略模型在嵌入式端的實現細節(jié),通過其解釋器自動執(zhí)行完畢。在這個框架下,基本只受限于主控本身內存,算力,以及作者本身的填坑速度了。

新的轉機

在2018年末,嘉楠耘智出了一款價格親民的高素質純國產AI芯片----K210。其低廉的價格(3美金以下),新穎的核心(RISC-V 64GC),強大的算力(~1TOPS),較低的功耗(0.3~0.5W),以及穩(wěn)定的貨源。吸引了Sipeed和TensorLayer開源社區(qū)的注意。圍繞著這款芯片,Sipeed開源了一系列的硬件模塊設計,制作了多款嵌入式板卡:MAIX Go/Bit/Dock/Duino…

?

Sipeed基于K210開發(fā)的相關模組

為了方便大家快速上手,Sipeed開發(fā)了易用的MaixPy (MicroPython)環(huán)境, 并兼容了多數OpenMV接口

Github: Sipeed - MaixPy Micropython env for Sipeed Maix boards. Contribute to sipeed/MaixPy development by creating an account on GitHub.?github.compYYBAGJWK8mACsN8AAAMCOnMuts716.jpg

?

?

雖然Maix板卡已經具備了運行MobileNet等典型網絡的能力,具備了實用性;然而,一直有個問題困擾著Sipeed和TensorLayer社區(qū)的小伙伴們:芯片原廠提供的模型轉換器nncase不好用啊。原廠的模型轉換器主要有以下問題:

  • 對于AI開發(fā)者不友好
    用戶需要經過:h5 -> pb -> tflite -> kmodel 多道工序才能完成轉換。
  • 出錯提示過于簡略
    nncase的出錯提示讓人摸不著頭腦,僅會報某層類型不支持,連層號都沒有。又因為層的轉換涉及到前后文順序,單靠一個出錯時的層號,很難排查。
  • C#工程過于模塊化
    雖然轉換器本身不是很大的工作量,但是nncase的C#工程過于細分,有三四級目錄,又沒有相應文檔說明,很多愛好者即使有心想改進nncase,卻也耐不住性子去翻閱這樣繁雜的工程。

那么好的芯片,沒有好用的工具怎么行,既然原廠的工具不好用,那么開源社區(qū)組團上吧–>

擼一個模型轉換器吧

Maix-EMC的初衷就是做一個好用的、好維護的、社區(qū)型、跨平臺模型轉換器,設計目標如下:

  1. 使用Python編寫,簡潔清晰,適當模塊化,讓有一定基礎的AI工程師能參與完善;
  2. 基于層結構的模型解析,對于以層為基礎的深度學習框架有一定移植性(如,TensorLayer, Keras);
  3. 使用扁平化,無需復雜解析的模型文件,即時載入內存,即時執(zhí)行;
  4. 嵌入式端解析器使用層類型進行解析,后端運算庫具備可插拔性(比如使用CMSIS-NN作為后端);

這個構想埋在心里很久,一直苦于業(yè)務繁忙沒有時間去實現,最近總算是抽空斷斷續(xù)續(xù)地開始挖了這個坑。。如果你只想使用Maxi-EMC,而不關心它的細節(jié),請看這篇文章:

低成本AIoT硬件深度學習部署實戰(zhàn)?zhuanlan.zhihu.com

Maxi-EMC的基礎架構

pYYBAGJWK86AAEr1AAChxj_qems526.jpg

左側:?EMC即這個工作的左側,將PC端的模型文件轉換成二進制扁平化的模型文件。PC端的模型文件我們選用了TensorLayer,因為TensorLayer的層定義高度比較合適,基本等同于kmodel定義的層的高度,兩者轉換基本只是作了 量化,某些層的合并優(yōu)化, 極大地加快了開發(fā)進度。反觀TensorFlow的pb文件里算子,低到了Add, mul的程度, 需要手工整合這些低層次算子到層定義,非常不便。

中間:這個工作的中間是kmodel文件,類似于字節(jié)碼或者說IR。這里模型文件沒有采用通用的protobuf(pb)或者flatbuffer(tflite), 因為對于嵌入式平臺來說,它們的解析以及內存消耗都太大。為了快速實現demo,并考慮嵌入式的效率,這里我們借用了k210 sdk中的kmodel v3格式。這個格式本是為K210設計,但是同樣適用于普通嵌入式平臺,只需新增通用層類型的定義。

右側:這個工作的右側是嵌入式硬件平臺上的kmodel解釋器(interpreter)。對于k210, 我們只需借用SDK本身的kpu.c, 稍作修改即可。對于普通單片機,我們只需將kpu.c中的卷積層計算函數替換成普通的cpu計算函數。這里的計算后端可以借用CMSIS-NN或者NNoM的計算后端,往上套上kmodel層參數的調用wrapper即可。

下面我們從左到右介紹整個流程的實現。

TensorLayer模型轉換為kmodel

層結構的轉換

由于TensorLayer使用基于層的模型結構描述,整個轉換過程比較簡單。入口文件是edge_model.py,其中gen_edge_layers_from_network將TensorLayer層轉換為EMC的層中間表示形式。這里首先通過platform_table查表選擇當前硬件平臺使用的TensorLayer層轉EMC層的函數表,以及打包模型的函數。

platform_table = {
#   platform       tl layer convertor   model generator
    'k210'      :   [tl_to_k210_table, gen_kmodel]
    #'stm32'    :   gen_stm32_layer_func_table,
} 

在tl_to_k210_table中,gen_edge_layer_from_network查找到對應的TensorLayer層類型的表項,并往后匹配到最長的列表,將該列表交給layer_generator 來生成 EMC中間層的list (可能會在前后加了上傳/下載/量化/去量化的dummy層)

tl_to_k210_table= {
#   TL layer class          layer_generator     merge
    'Dense'                 :[gen_fc_layer,         [[],]] ,
    'Flatten'               :[gen_flatten_layer,    [[],]] ,
    'Reshape'               :[None,                 [[],]] ,
    'GlobalMaxPool2d'       :[gen_gmaxpool2d_layer, [[],]] ,
    'GlobalMeanPool2d'      :[gen_gavgpool2d_layer, [[],]] ,
    'MaxPool2d'             :[gen_maxpool2d_layer,  [[],]] ,
    'MeanPool2d'            :[gen_avgpool2d_layer,  [[],]] ,
    'Concat'                :[gen_concat_layer,     [[],]] ,
    'Conv2d'                :[gen_k210_conv_layer,  [[], ['BatchNorm'],]] ,
    'DepthwiseConv2d'       :[gen_k210_conv_layer,  [[], ['BatchNorm'],]] ,
    'ZeroPad2d'             :[gen_k210_conv_layer,  [['Conv2d'], \
                                                     ['Conv2d', 'BatchNorm'], \
                                                     ['DepthwiseConv2d'], \
                                                     ['DepthwiseConv2d', 'BatchNorm']]] ,
    'DummyDequant'          :[gen_dequant_layer,    [[],]] ,  
    'SoftMax'               :[gen_softmax_layer,    [[],]] ,  
}

量化操作

由于TensorLayer目前沒有很好的量化API,所以在EMC的層轉換中附帶實現了參數量化。
edge_quant.py中可選minmax或者kld量化。實測對于小模型,minmax還是最簡單直接,快速有效的方式。KLD方式可能略有提升,但有時卻會負優(yōu)化。。為了進一步提升精度,我們還使用了Channel Wise的量化方式來降低精度損失。對每一個Channel使用不同的量化參數,直到最后再合并,經測試在大通道的模型中會有一定的優(yōu)化效果。

后處理及打包

至此我們初步將TensorLayer層轉換成了一系列層列表,我們再使用optimize_layers來優(yōu)化層列表,去除一些抵消的層(如相鄰的量化/去量化層),進行一些可選的后處理(比如k210的stride修復步驟)。

然后我們使用gen_kmodel將層列表轉換成kmodel層列表中的每個層都有to_kmodel方法,調用該方法即可獲得當前層符合kmodel格式的layer body的bytearray結果。gen_kmodel再把所有層的body堆疊在一起,統計好最大的動態(tài)內存需求,加好頭部,即得到了kmodel。

EMC 層支持的添加

這里簡單介紹下如何添加新的層支持。首先在edge_model.py的tl_to_k210_table里加上你需要添加的TensorLayer層與EMC層的轉換表項。然后在對應的xxx_layer.py中加上對應的實現。K210相關的加速層在k210_layer.py中實現(目前已經基本實現,但是需要修復一些bug),CPU計算的非加速層,在edge_layer中實現。只需模仿其中的層的實現,對每個層類型,完成以下一個函數和一個類:

  • gen_xxx_layer: 輸入TL layer list, 轉換成EMC layer list;
  • class xxx_Layer: 需要實現init方法(填充層信息),以及to_kmodel方法(按kmodel格式填充信息,返回打包的bytearray)

事實上,你可以實現自定義的to_xxxmodel方法,在此框架上實現你自己的模型格式。

kmodel簡介

kmodel是一個自定義的,扁平化的模型存儲格式,模型格式的封裝已經在EMC代碼里完成,這里簡要介紹一下:在EMC中,我們調用了dissect.cstruct, 這是pyhton解析c結構體的庫, 很方便我們使用k210的kpu.c中關于kmodel的結構體定義。在EMC中,這部分定義放在k210_constant.py中:

"
typedef struct
{
    uint32 version;			
    uint32 flags;
    uint32 arch;				
    uint32 layers_length;		
    uint32 max_start_address;
    uint32 main_mem_usage;	
    uint32 output_count;		
} kpu_model_header_t;
typedef struct
{
    uint32 address;
    uint32 size;
} kpu_model_output_t;
typedef struct
{
    uint32 type;
    uint32 body_size;
} kpu_model_layer_header_t;
...

kmodel 頭部是kpu_model_header_t, 描述了 版本,量化位數,層數,最大內存占用大小(驅動中一次性申請該模型需要的動態(tài)內存),輸出節(jié)點數量。在頭部之后,排列著若干個kpu_model_output_t,描述輸出節(jié)點的信息。在輸出節(jié)點信息之后,排列著所有層的頭部信息:kpu_model_layer_header_t,依次描述層的類型,層body的大小。在層頭部信息之后,就按層信息依次排列層body數據,其中某些部分會要求一定的字節(jié)對齊。

層類型定義在edge_constant.py中,在原始的kpu.h的定義上稍作修改,區(qū)分了k210專用層和普通層(這里是為了快速移植K210驅動才使用了K210專用層,理論上僅定義一套通用層標準比較好)

K210的kmodel解釋器的實現

可以參見kpu.c, 驅動會按順序讀取kmodel每一層的層信息,根據層類型執(zhí)行對應函數。
需要注意的是上傳/下載操作。K210內存分為6M CPU內存 和 2M KPU內存。使用KPU計算的層,需要將待計算的數據上傳到KPU內存。在KPU中,可以連續(xù)計算很多層CONV相關計算,而無需將結果下載到CPU內存。但是一旦下一層是需要CPU運算的層,則需要進行一次下載才能繼續(xù)運行。所以,我們需要留意TensorLayer層的順序,在需要切換KPU/CPU運行的層前后,插入上傳,下載的dummy 層。在EMC中,我們使用meta_info[‘is_inai’]字段確認當前的待計算內容是否在AI內存。

另外,KPU計算,使用的2M內存,是以乒乓形式使用,即輸入數據在開端,則輸出結果在末端進入下一層后,上一層的輸出結果作為了輸入結果,在末端,計算結果放到了開端。
如此往復計算,EMC中meta_info[‘conv_idx’]記錄了當前的卷積層序號,進而可以確認當前的輸出結果所在KPU內存的偏移。

其它注意點,需要下載kpu.c查看:https://github.com/kendryte/kendryte-standalone-sdk/blob/develop/lib/drivers/kpu.c

測試

我們使用Maix-EMC測試轉換了mbnet的每一層,與PC原始結果對比:

?


同一張圖片,alpha=1.0, top5的預測概率:

pYYBAGJWK9GAWaIsAABqWKAmcmU005.jpg

同一張圖片,alpha=0.75, top5的預測概率:

pYYBAGJWK9KAchBPAAB18ObyBUQ835.jpg

同一張圖片,alpha=0.5, top5的預測概率:

poYBAGJWK9SAENmNAAB5mVv4qb0866.jpg

可以看到相對PC端的結果,K210的計算結果退化了3~6%,是否是轉換器原因造成的呢?
我們對比下谷歌的TFLite的量化工具的測試數據:

poYBAGJWK9WAMIqOAABJUSH1w10655.jpg

發(fā)現對于MobileNet來說,TFLite的量化也造成了5.6%的損失,所以這是正常的損失。(當然這里的tflite的精度是指的是數據集總體的精度損失,我前面僅測了一張圖片的概率損失,有差別)。雖然我們有很多方式改善訓練后量化損失,但是基本都會膨脹模型體積,所以在這里不再贅述。

小結

目前Maix-EMC完成了初步簡單結構的模型轉換功能,可以基于TensorLayer框架快速部署到K210普通上,對于復雜模型仍然需要社區(qū)小伙伴一起完善。

?

下載該資料的人也在下載 下載該資料的人還在閱讀
更多 >

評論

查看更多

下載排行

本周

  1. 1山景DSP芯片AP8248A2數據手冊
  2. 1.06 MB  |  532次下載  |  免費
  3. 2RK3399完整板原理圖(支持平板,盒子VR)
  4. 3.28 MB  |  339次下載  |  免費
  5. 3TC358743XBG評估板參考手冊
  6. 1.36 MB  |  330次下載  |  免費
  7. 4DFM軟件使用教程
  8. 0.84 MB  |  295次下載  |  免費
  9. 5元宇宙深度解析—未來的未來-風口還是泡沫
  10. 6.40 MB  |  227次下載  |  免費
  11. 6迪文DGUS開發(fā)指南
  12. 31.67 MB  |  194次下載  |  免費
  13. 7元宇宙底層硬件系列報告
  14. 13.42 MB  |  182次下載  |  免費
  15. 8FP5207XR-G1中文應用手冊
  16. 1.09 MB  |  178次下載  |  免費

本月

  1. 1OrCAD10.5下載OrCAD10.5中文版軟件
  2. 0.00 MB  |  234315次下載  |  免費
  3. 2555集成電路應用800例(新編版)
  4. 0.00 MB  |  33566次下載  |  免費
  5. 3接口電路圖大全
  6. 未知  |  30323次下載  |  免費
  7. 4開關電源設計實例指南
  8. 未知  |  21549次下載  |  免費
  9. 5電氣工程師手冊免費下載(新編第二版pdf電子書)
  10. 0.00 MB  |  15349次下載  |  免費
  11. 6數字電路基礎pdf(下載)
  12. 未知  |  13750次下載  |  免費
  13. 7電子制作實例集錦 下載
  14. 未知  |  8113次下載  |  免費
  15. 8《LED驅動電路設計》 溫德爾著
  16. 0.00 MB  |  6656次下載  |  免費

總榜

  1. 1matlab軟件下載入口
  2. 未知  |  935054次下載  |  免費
  3. 2protel99se軟件下載(可英文版轉中文版)
  4. 78.1 MB  |  537798次下載  |  免費
  5. 3MATLAB 7.1 下載 (含軟件介紹)
  6. 未知  |  420027次下載  |  免費
  7. 4OrCAD10.5下載OrCAD10.5中文版軟件
  8. 0.00 MB  |  234315次下載  |  免費
  9. 5Altium DXP2002下載入口
  10. 未知  |  233046次下載  |  免費
  11. 6電路仿真軟件multisim 10.0免費下載
  12. 340992  |  191187次下載  |  免費
  13. 7十天學會AVR單片機與C語言視頻教程 下載
  14. 158M  |  183279次下載  |  免費
  15. 8proe5.0野火版下載(中文版免費下載)
  16. 未知  |  138040次下載  |  免費
RM新时代网站-首页