1. Resnet50簡介
ResNet50網(wǎng)絡(luò)是2015年由微軟實(shí)驗(yàn)室的何愷明提出,獲得ILSVRC2015圖像分類競賽第一名。在ResNet網(wǎng)絡(luò)提出之前,傳統(tǒng)的卷積神經(jīng)網(wǎng)絡(luò)都是將一系列的卷積層和池化層堆疊得到的,但當(dāng)網(wǎng)絡(luò)堆疊到一定深度時(shí),就會(huì)出現(xiàn)退化問題。 殘差網(wǎng)絡(luò)的特點(diǎn)是容易優(yōu)化,并且能夠通過增加相當(dāng)?shù)纳疃葋硖岣邷?zhǔn)確率。其內(nèi)部的殘差塊使用了跳躍連接,緩解了在深度神經(jīng)網(wǎng)絡(luò)中增加深度帶來的梯度消失問題。
本教程基于圖像分類算法ResNet50的訓(xùn)練和部署到EASY-EAI-Nano(RV1126)進(jìn)行說明。

2. 準(zhǔn)備數(shù)據(jù)集
2.1 數(shù)據(jù)集下載
本教程以車輛分類算法為例
解壓完成后得到以下兩個(gè)文件夾:

打開可以看到一共10類汽車:

類別名稱 | 類別索引號(hào) |
SUV | 0 |
BUS | 1 |
family sedan | 2 |
fire engine | 3 |
heavy truck | 4 |
jeep | 5 |
mini bus | 6 |
racing car | 7 |
taxi | 8 |
truck | 9 |
3. ResNet50圖像分類訓(xùn)練
3.1 訓(xùn)練源碼下載
得到下圖所示目錄:

把數(shù)據(jù)集解壓到當(dāng)前目錄:

3.2 訓(xùn)練模型
進(jìn)入anconda的pyTorch環(huán)境,切換到訓(xùn)練源碼目錄執(zhí)行以下指令開始訓(xùn)練:
python train.py
執(zhí)行結(jié)果如下圖所示:

訓(xùn)練結(jié)束后test loss結(jié)果如下所示:

訓(xùn)練結(jié)束后test accuracy結(jié)果如下所示:

生成的最優(yōu)模型如下所示:

3.3 在PC端測試模型
在訓(xùn)練源碼目錄執(zhí)行以下指令,測試模型(生成模型名稱不一致則修改predict.py腳本):
python predict.py

結(jié)果類別索引號(hào)為1——BUS, 測試結(jié)果正確。
3.4 pth模型轉(zhuǎn)換為onnx模型
執(zhí)行以下指令把pytorch的pth模型轉(zhuǎn)換onxx模型:
python pth_to_onnx.py

生成ONNX模型如下所示:

4. rknn-toolkit模型轉(zhuǎn)換
4.1 rknn-toolkit模型轉(zhuǎn)換環(huán)境搭建
onnx模型需要轉(zhuǎn)換為rknn模型才能在EASY-EAI-Nano運(yùn)行,所以需要先搭建rknn-toolkit模型轉(zhuǎn)換工具的環(huán)境。當(dāng)然tensorflow、tensroflow lite、caffe、darknet等也是通過類似的方法進(jìn)行模型轉(zhuǎn)換,只是本教程onnx為例。
4.1.1 概述
模型轉(zhuǎn)換環(huán)境搭建流程如下所示:

4.1.2 下載模型轉(zhuǎn)換工具
為了保證模型轉(zhuǎn)換工具順利運(yùn)行,請(qǐng)下載網(wǎng)盤里”AI算法開發(fā)/RKNN-Toolkit模型轉(zhuǎn)換工具/rknn-toolkit-v1.7.3/docker/rknn-toolkit-1.7.3-docker.tar.gz”。
4.1.3 把工具移到ubuntu18.04
把下載完成的docker鏡像移到我司的虛擬機(jī)ubuntu18.04的rknn-toolkit目錄,如下圖所示:

4.1.4 運(yùn)行模型轉(zhuǎn)換工具環(huán)境
在該目錄打開終端:

執(zhí)行以下指令加載模型轉(zhuǎn)換工具docker鏡像:
docker load --input /home/developer/rknn-toolkit/rknn-toolkit-1.7.3-docker.tar.gz
執(zhí)行以下指令進(jìn)入鏡像bash環(huán)境:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb rknn-toolkit:1.7.3 /bin/bash
現(xiàn)象如下圖所示:

輸入“python”加載python相關(guān)庫,嘗試加載rknn庫,如下圖環(huán)境測試成功:

至此,模型轉(zhuǎn)換工具環(huán)境搭建完成。
4.2 模型轉(zhuǎn)換為RKNN
EASY EAI Nano支持.rknn后綴的模型的評(píng)估及運(yùn)行,對(duì)于常見的tensorflow、tensroflow lite、caffe、darknet、onnx和Pytorch模型都可以通過我們提供的 toolkit 工具將其轉(zhuǎn)換至 rknn 模型,而對(duì)于其他框架訓(xùn)練出來的模型,也可以先將其轉(zhuǎn)至 onnx 模型再轉(zhuǎn)換為 rknn 模型。 模型轉(zhuǎn)換操作流程入下圖所示:

4.2.1 模型轉(zhuǎn)換Demo下載
把resnet50_model_convert.tar.bz2和quant_dataset.zip解壓到虛擬機(jī),如下圖所示:

4.2.2 進(jìn)入模型轉(zhuǎn)換工具docker環(huán)境
執(zhí)行以下指令把工作區(qū)域映射進(jìn)docker鏡像,其中/home/developer/rknn-toolkit/model_convert_test為工作區(qū)域,/test為映射到docker鏡像,/dev/bus/usb:/dev/bus/usb為映射usb到docker鏡像:
docker run -t -i --privileged -v /dev/bus/usb:/dev/bus/usb -v /home/developer/rknn-toolkit/model_convert_test:/test rknn-toolkit:1.7.3 /bin/bash
執(zhí)行成功如下圖所示:

4.2.3 模型轉(zhuǎn)換Demo目錄介紹
模型轉(zhuǎn)換測試Demo由resnet50_model_convert和quant_dataset組成。resnet50_model_convert存放軟件腳本,quant_dataset存放量化模型所需的數(shù)據(jù)。如下圖所示:

resnet50_model_convert文件夾存放以下內(nèi)容,如下圖所示:

4.2.4 生成量化圖片列表
在docker環(huán)境切換到模型轉(zhuǎn)換工作目錄:
cd /test/resnet50_model_convert
如下圖所示:

執(zhí)行gen_list.py生成量化圖片列表:
python gen_list.py
命令行現(xiàn)象如下圖所示:

生成“量化圖片列表”如下文件夾所示:

4.2.5 onnx模型轉(zhuǎn)換為rknn模型
rknn_convert.py腳本默認(rèn)進(jìn)行int8量化操作,腳本代碼清單如下所示:
import os import urllib import traceback import time import sys import numpy as np import cv2 from rknn.api import RKNN ONNX_MODEL = '10class_ResNet50.onnx' RKNN_MODEL = './10class_ResNet50.rknn' DATASET = './pic_path.txt' QUANTIZE_ON = True if __name__ == '__main__': # Create RKNN object rknn = RKNN(verbose=True) if not os.path.exists(ONNX_MODEL): print('model not exist') exit(-1) # pre-process config print('--> Config model') rknn.config(reorder_channel='0 1 2', mean_values=[[123.67, 116.28,103.53]], std_values=[[58.395, 57.12, 57.375]], optimization_level=3, target_platform = 'rv1126', output_optimize=1, quantize_input_node=QUANTIZE_ON) print('done') # Load ONNX model print('--> Loading model') ret = rknn.load_onnx(model=ONNX_MODEL) if ret != 0: print('Load failed!') exit(ret) print('done') # Build model print('--> Building model') ret = rknn.build(do_quantization=QUANTIZE_ON, dataset=DATASET) if ret != 0: print('Build resnet failed!') exit(ret) print('done') # Export RKNN model print('--> Export RKNN model') ret = rknn.export_rknn(RKNN_MODEL) if ret != 0: print('Export resnet failed!') exit(ret) print('done')
把onnx模型10class_ResNet50.onnx放到resnet50_model_convert目錄,并執(zhí)行rknn_convert.py腳本進(jìn)行模型轉(zhuǎn)換:
python rknn_convert.py
生成模型如下圖所示,此模型可以在rknn-toolkit環(huán)境和EASY EAI Nano環(huán)境運(yùn)行:

4.2.6 運(yùn)行rknn模型
用predict.py腳本在PC端的環(huán)境下可以運(yùn)行rknn的模型,如下圖所示:

predict.py腳本程序清單如下所示:
import os import urllib import traceback import time import sys import numpy as np import cv2 import random from rknn.api import RKNN RKNN_MODEL = '10class_ResNet50.rknn' IMG_PATH = './test-1.jpg' BOX_THRESH = 0.25 NMS_THRESH = 0.6 CLASSES = ("SUV", "bus", "family sedan", "fire engine", "heavy truck", "jeep", "minibus", "racing car", "taxi", "truck") def show_outputs(output): print("softmax output:", output) max_confidence = np.max(output) index = np.where(output == max_confidence) print("max confidence:", max_confidence) print("max confidence index:", index[0][0]) print("CLASSES predict: ", CLASSES[index[0][0]]) def softmax(x): return np.exp(x)/sum(np.exp(x)) if __name__ == '__main__': # Create RKNN object rknn = RKNN(verbose=True) print('--> Loading model') ret = rknn.load_rknn(RKNN_MODEL) if ret != 0: print('load rknn model failed') exit(ret) print('done') # init runtime environment print('--> Init runtime environment') ret = rknn.init_runtime() # ret = rknn.init_runtime('rv1126', device_id='1126') if ret != 0: print('Init runtime environment failed') exit(ret) print('done') # Set inputs img = cv2.imread(IMG_PATH) img = cv2.cvtColor(img, cv2.COLOR_BGR2RGB) resize_img = cv2.resize(img,(224,224)) # Inference print('--> Running model') outputs = rknn.inference(inputs=[resize_img]) print("outputs[0]:", outputs[0]) print("outputs[0].shape:", outputs[0].shape) show_outputs(softmax(np.array(outputs[0][0]))) print('done') rknn.release()
執(zhí)行結(jié)果如下圖所示:

4.2.7 模型預(yù)編譯
由于rknn模型用NPU API在EASY EAI Nano加載的時(shí)候啟動(dòng)速度會(huì)很慢,在評(píng)估完模型精度沒問題的情況下,建議進(jìn)行模型預(yù)編譯。預(yù)編譯的時(shí)候需要通過EASY EAI Nano主板的環(huán)境,所以請(qǐng)務(wù)必接上adb口與ubuntu保證穩(wěn)定連接。
板子端接線如下圖所示,撥碼開關(guān)需要是adb:

虛擬機(jī)要保證接上adb設(shè)備:

由于在虛擬機(jī)里ubuntu環(huán)境與docker環(huán)境對(duì)adb設(shè)備資源是競爭關(guān)系,所以需要關(guān)掉ubuntu環(huán)境下的adb服務(wù),且在docker里面通過apt-get安裝adb軟件包。以下指令在ubuntu環(huán)境與docker環(huán)境里各自執(zhí)行:

在docker環(huán)境里執(zhí)行adb devices,現(xiàn)象如下圖所示則設(shè)備連接成功:

運(yùn)行precompile_rknn.py腳本把模型執(zhí)行預(yù)編譯:
python precompile_rknn.py
執(zhí)行效果如下圖所示,生成預(yù)編譯模型10class_ResNet50_pre.rknn:

至此預(yù)編譯部署完成,模型轉(zhuǎn)換步驟已全部完成。生成如下預(yù)編譯后的int8量化模型:

至此RKNN模型生成完畢,注意預(yù)編譯模型只能在板卡端執(zhí)行。
5. ResNet50圖像分類部署
5.1 模型部署示例介紹
本小節(jié)展示ResNet50模型的在EASY EAI Nano的部署過程,該模型僅經(jīng)過簡單訓(xùn)練供示例使用,不保證模型精度。
5.2 開發(fā)環(huán)境準(zhǔn)備
如果您初次閱讀此文檔,請(qǐng)閱讀《入門指南/開發(fā)環(huán)境準(zhǔn)備/Easy-Eai編譯環(huán)境準(zhǔn)備與更新》,并按照其相關(guān)的操作,進(jìn)行編譯環(huán)境的部署。
在PC端Ubuntu系統(tǒng)中執(zhí)行run腳本,進(jìn)入EASY-EAI編譯環(huán)境,具體如下所示。
cd ~/develop_environment ./run.sh

5.3 源碼下載以及例程編譯
下載ResNet50 C Demo示例文件。
下載程序包移至ubuntu環(huán)境后,執(zhí)行以下指令解壓:
tar -xvf resnet50_classification_C_demo.tar.bz2
下載解壓后如下圖所示:

在EASY-EAI編譯環(huán)境下,切換到例程目錄執(zhí)行編譯操作:
cd /opt/rknn-toolkit/resnet50_classification_C_demo/ ./build.sh
注:
* 由于依賴庫部署在板卡上,因此交叉編譯過程中必須保持adb連接。

5.4 在開發(fā)板執(zhí)行ResNet50 圖像分類算法
在EASY-EAI編譯環(huán)境下,在例程目錄執(zhí)行以下指令把可執(zhí)行程序推送到開發(fā)板端:
cp resnet_classification_demo_release/ /mnt/userdata/ -rf
通過按鍵Ctrl+Shift+T創(chuàng)建一個(gè)新窗口,執(zhí)行adb shell命令,進(jìn)入板卡運(yùn)行環(huán)境:
adb shell

進(jìn)入板卡后,定位到例程上傳的位置,如下所示:
cd /userdata/resnet_classification_demo_release/
運(yùn)行例程命令如下所示:
./resnet_classification_demo
執(zhí)行結(jié)果如下圖所示,算法執(zhí)行時(shí)間約為35ms:

至此,ResNet50圖像分類例程已成功在板卡運(yùn)行。
-
開發(fā)板
+關(guān)注
關(guān)注
25文章
5389瀏覽量
100899 -
resnet
+關(guān)注
關(guān)注
0文章
13瀏覽量
3271 -
rv1126
+關(guān)注
關(guān)注
0文章
106瀏覽量
3259
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
Qt程序部署到瑞星微RV1126開發(fā)板上,使用QCursor::pos()獲取鼠標(biāo)為零是為什么?
【R329開發(fā)板評(píng)測】實(shí)機(jī)測試Resnet50

RV1126-AI開發(fā)手記(一)Resnet50性能評(píng)估

RV1126開發(fā)板數(shù)據(jù)手冊(cè)
RV1126 實(shí)現(xiàn)人臉檢測方案

基于RV1126開發(fā)板網(wǎng)絡(luò)配置方法

RV1126 yolov8訓(xùn)練部署教程

基于RV1126開發(fā)板實(shí)現(xiàn)駕駛員行為檢測方案

基于RV1126開發(fā)板實(shí)現(xiàn)人臉檢測方案

基于RV1126開發(fā)板實(shí)現(xiàn)自學(xué)習(xí)圖像分類方案

基于RV1126開發(fā)板實(shí)現(xiàn)人臉檢測方案

基于RV1126開發(fā)板實(shí)現(xiàn)人臉檢測方案

評(píng)論