認(rèn)識(shí)自己,是人類的終極問(wèn)題;而讓AI認(rèn)識(shí)自己,則是人工智能覺(jué)醒的第一步。為此,國(guó)內(nèi)知名嵌入式教育專家韋東山老師團(tuán)隊(duì)使用做了個(gè)有趣的事情——讓開(kāi)發(fā)板可以“認(rèn)識(shí)”自己。
本文將從數(shù)據(jù)集的標(biāo)注開(kāi)始,進(jìn)行在100ASK_V853-PRO開(kāi)發(fā)板上部署YOLOV5自訓(xùn)練模型的全過(guò)程演示,內(nèi)容包括訓(xùn)練自定義模型、導(dǎo)出模型、轉(zhuǎn)換模型、模型部署......并在最終實(shí)現(xiàn)開(kāi)發(fā)板以自我為目標(biāo)的檢測(cè)功能,下面展示“我看我自己”的展示端側(cè)最終檢驗(yàn)效果圖:
下載數(shù)據(jù)標(biāo)注工具
首先來(lái)到數(shù)據(jù)標(biāo)注工具下載的地方。
點(diǎn)擊上述紅框下載,下載完成后解壓壓縮包,雙擊打開(kāi)labelImg.exe文件。
打開(kāi)后等待運(yùn)行,運(yùn)行完成后會(huì)進(jìn)入如下標(biāo)注工作界面。
關(guān)于LabelImg更多的使用方法,請(qǐng)?jiān)L問(wèn):https://github.com/heartexlabs/labelImg
由于LabelImg會(huì)預(yù)先提供一些類供您使用,需要手動(dòng)刪除這些類,使得您可以標(biāo)注自己的數(shù)據(jù)集。步驟如下所示:
進(jìn)入LabelImg程序目錄中的data目錄中,打開(kāi)predefined_classes.txt文件,刪除文件中所有預(yù)定義的類后保存并退出即可。
創(chuàng)建數(shù)據(jù)集目錄
在任意工作目錄中創(chuàng)建images文件夾和labels文件夾分別存放圖像數(shù)據(jù)集和標(biāo)注信息。這里我演示僅使用少量圖像樣本進(jìn)行標(biāo)注,在實(shí)際項(xiàng)目中需要采集足夠的圖像進(jìn)行標(biāo)注才拿滿足模型的準(zhǔn)確率和精度。
例如我在100ask-yolov5-image目錄中創(chuàng)建有images文件夾和labels文件夾,如下所示,創(chuàng)建images文件,存放圖像數(shù)據(jù)集,創(chuàng)建labels文件夾,該文件夾用于后續(xù)存放標(biāo)注數(shù)據(jù)。
標(biāo)注圖像
打開(kāi)LabelImg軟件后,使用軟件打開(kāi)數(shù)據(jù)集圖像文件夾,如下所示:
打開(kāi)后,修改輸出label的文件夾為我們創(chuàng)建的數(shù)據(jù)集目錄下的labels文件夾
下面我演示標(biāo)注過(guò)程,以百問(wèn)網(wǎng)的開(kāi)發(fā)板為例,標(biāo)注三塊開(kāi)發(fā)板,當(dāng)你點(diǎn)擊Save后即表示標(biāo)注完成,標(biāo)注完成后后會(huì)在labels目錄下生成classes.txt(類別)和圖像中標(biāo)注的類別即位置信息。
經(jīng)過(guò)標(biāo)注大量的圖像后,labels文件夾如下圖所示:
劃分訓(xùn)練集和驗(yàn)證集
在模型訓(xùn)練中,需要有訓(xùn)練集和驗(yàn)證集??梢院?jiǎn)單理解為網(wǎng)絡(luò)使用訓(xùn)練集去訓(xùn)練,訓(xùn)練出來(lái)的網(wǎng)絡(luò)使用驗(yàn)證集驗(yàn)證。在總數(shù)據(jù)集中訓(xùn)練集通常應(yīng)占80%,驗(yàn)證集應(yīng)占20%。所以將我們標(biāo)注的數(shù)據(jù)集按比例進(jìn)行分配。
在yolov5-6.0項(xiàng)目目錄下創(chuàng)建100ask文件夾(該文件夾名可自定義),在100ask文件夾中創(chuàng)建train文件夾(存放訓(xùn)練集)和創(chuàng)建val文件夾(存放驗(yàn)證集)。
在train文件夾中創(chuàng)建images文件夾和labels文件夾。其中images文件夾存放總數(shù)據(jù)集的80%的圖像文件,labels文件夾存放與images中的文件對(duì)應(yīng)的標(biāo)注文件。
在val文件夾中創(chuàng)建images文件夾和labels文件夾。其中images文件夾存放總數(shù)據(jù)集的20%的圖像文件,labels文件夾存放與images中的文件對(duì)應(yīng)的標(biāo)注文件。
創(chuàng)建數(shù)據(jù)集配置文件
進(jìn)入yolov5-6.0data目錄下,創(chuàng)建data.yaml,文件內(nèi)容如下所示:
train: 100ask rainimages # train images val: 100askvalimages # val images nc: 3 # number of classes names: ['T113', 'K510', 'V853'] # class names
創(chuàng)建模型配置文件
進(jìn)入models目錄下,拷貝yolov5s.yaml文件,粘貼并models目錄下重命名為100ask_my-model.yaml,例如:
修改100ask_my-model.yaml中類的數(shù)目為自己訓(xùn)練模型的類數(shù)目。
修改訓(xùn)練函數(shù)
打開(kāi)yolov5-6.0項(xiàng)目文件夾中的train.py,修改數(shù)據(jù)配置文件路徑,如下圖紅框所示:
printf("hel parser.add_argument('--cfg', type=str, default='models/100ask_my-model.yaml', help='model.yaml path') parser.add_argument('--data', type=str, default=ROOT / 'data/data.yaml', help='dataset.yaml path')lo world!");
訓(xùn)練模型
在conda終端的激活yolov5環(huán)境,激活后進(jìn)入yolov5-6.0項(xiàng)目文件夾。執(zhí)行python train.py,如下圖所示:
程序默認(rèn)迭代300次,等待訓(xùn)練完成...
訓(xùn)練完成后結(jié)果會(huì)保存在runs rain目錄下最新一次的訓(xùn)練結(jié)果,如上圖所示,此次訓(xùn)練的最好模型和最后訓(xùn)練的模型保存在以下目錄中
runs rainexp7weights
驗(yàn)證模型
修改val.py函數(shù),修改如下
parser.add_argument('--data', type=str, default=ROOT / 'data/data.yaml', help='dataset.yaml path') parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'runs/train/exp7/weights/best.pt', help='model.pt path(s)')
修改models文件夾下的yolo.py
class Model(nn.Module): def __init__(self, cfg='100ask_my-model.yaml', ch=3, nc=None, anchors=None): # model, input channels, number of classes
打開(kāi)conda終端輸入python val.py
執(zhí)行完成后的結(jié)果保存在runsvalexp文件下。
預(yù)測(cè)圖像
在data目錄中新建100ask-images文件夾存放待檢測(cè)的圖像和視頻文件。
修改detect.py函數(shù)中,模型的路徑與檢測(cè)圖像路徑。
parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'runs/train/exp7/weights/best.pt', help='model path(s)') parser.add_argument('--source', type=str, default=ROOT / 'data/100ask-images', help='file/dir/URL/glob, 0 for webcam')
檢測(cè)效果如下圖所示:
導(dǎo)出ONNX模型
修改export.py函數(shù)
parser.add_argument('--data', type=str, default=ROOT / 'data/data.yaml', help='dataset.yaml path') parser.add_argument('--weights', type=str, default=ROOT / 'runs/train/exp7/weights/best.pt', help='weights path')
在conda終端輸入:
printf("hello world!"); python export.py --include onnx --dynamic
導(dǎo)出的模型會(huì)與輸入的模型位于同一路徑下,假設(shè)我輸入的模型位于:runs rainexp7weights
簡(jiǎn)化模型
簡(jiǎn)化模型前需要用到onnxruntime依賴包,輸入以下命令安裝:
pip install onnxruntime==1.13.1 -i https://pypi.doubanio.com/simple/
簡(jiǎn)化命令如下:
python -m onnxsim <輸入模型> <輸出模型> --input-shape <輸入圖像尺寸>
例如輸入模型路徑為runs/train/exp7/weights/best.onnx,輸出模型路徑為runs/train/exp7/weights/best-sim.onnx,輸入圖像尺寸固定為640x640。
python -m onnxsim runs/train/exp7/weights/best.onnx runs/train/exp7/weights/best-sim.onnx --input-shape 1,3,640,640
查看模型
可以看到輸入已經(jīng)固定為640x640,可看到模型有 4 個(gè)輸出節(jié)點(diǎn),其中 ouput 節(jié)點(diǎn)為后處理解析后的節(jié)點(diǎn);在實(shí)際測(cè)試的過(guò)程中,發(fā)現(xiàn) NPU 量化操作后對(duì)后處理的運(yùn)算非常不友好,輸出數(shù)據(jù)偏差較大,所以我們可以將后處理部分放在 CPU 運(yùn)行;因此在導(dǎo)入模型時(shí)保留 350,498, 646 三個(gè)后處理解析前的輸出節(jié)點(diǎn)即可。
驗(yàn)證模型
模型需要修改為簡(jiǎn)化后的模型路徑。
新建文件夾存放固定的輸入圖像尺寸。假設(shè)上述中我設(shè)置輸入圖像尺寸為640x640,那么此時(shí)我在data目錄下新建100ask-images-640文件夾存放640x640的圖像作為待測(cè)數(shù)據(jù)。
修改detect.py函數(shù)
parser.add_argument('--weights', nargs='+', type=str, default=ROOT / 'runs/train/exp7/weights/best-sim.onnx', help='model path(s)') parser.add_argument('--source', type=str, default=ROOT / 'data/100ask-images-640', help='file/dir/URL/glob, 0 for webcam')
在conda終端輸入:
python detect.py
通過(guò)輸出信息可知:檢測(cè)結(jié)果存儲(chǔ)在runsdetectexp6,檢測(cè)結(jié)果如下:
轉(zhuǎn)換模型
將簡(jiǎn)化后的best-sim.onnx模型傳入配置到NPU模型轉(zhuǎn)換工具的虛擬機(jī)中,創(chuàng)建模型工具目錄,包含模型文件,量化文件夾data(存放量化圖片),dataset.txt文件(存放量化圖片的路徑)。
buntu@ubuntu2004:~/100ask-yolov5-test$ tree . ├── best-sim.onnx ├── data │ └── test01.jpg └── dataset.txt 1 directory, 5 files
導(dǎo)入模型前需要知道我們要保留的輸出節(jié)點(diǎn),由之前查看到我們輸出的三個(gè)后處理節(jié)點(diǎn)為:350,498,646 。
pegasus import onnx --model best-sim.onnx --output-data best-sim.data --output-model best-sim.json --outputs "350 498 646"
導(dǎo)入生成兩個(gè)文件,分別是是 yolov5s-sim.data 和 yolov5s-sim.json 文件,兩個(gè)文件是 YOLO V5 網(wǎng)絡(luò)對(duì)應(yīng)的芯原內(nèi)部格式表示文件,data 文件儲(chǔ)存權(quán)重,cfg 文件儲(chǔ)存模型。
YML 文件對(duì)網(wǎng)絡(luò)的輸入和輸出的超參數(shù)進(jìn)行描述以及配置,這些參數(shù)包括,輸入輸出 tensor 的形狀,歸一化系數(shù) (均值,零點(diǎn)),圖像格式,tensor 的輸出格式,后處理方式等等
pegasus generate inputmeta --model best-sim.json --input-meta-output best-sim_inputmeta.yml
pegasus generate postprocess-file --model best-sim.json --postprocess-file-output best-sim_postprocess_file.yml
修改 best-sim_inputmeta.yml 文件中的的 scale 參數(shù)為 0.0039216(1/255),目的是對(duì)輸入 tensor 進(jìn)行歸一化,和網(wǎng)絡(luò)進(jìn)行訓(xùn)練的時(shí)候是對(duì)應(yīng)的。
vi best-sim_inputmeta.yml
修改過(guò)程如下圖所示:
生成量化表文件,使用非對(duì)稱量化,uint8,修改 --batch-size 參數(shù)為你的 dataset.txt 里提供的圖片數(shù)量。如果原始網(wǎng)絡(luò)使用固定的batch_size,請(qǐng)使用固定的batch_size,如果原始網(wǎng)絡(luò)使用可變batch_size,請(qǐng)將此參數(shù)設(shè)置為1。
pegasus quantize --model best-sim.json --model-data best-sim.data --batch-size 1 --device CPU --with-input-meta best-sim_inputmeta.yml --rebuild --model-quantize best-sim.quantize --quantizer asymmetric_affine --qtype uint8
利用前文的量化表執(zhí)行預(yù)推理,得到推理 tensor
pegasus inference --model best-sim.json --model-data best-sim.data --batch-size 1 --dtype quantized --model-quantize best-sim.quantize --device CPU --with-input-meta best-sim_inputmeta.yml --postprocess-file best-sim_postprocess_file.yml
輸出的模型可以在 ovxilb/100ask-best-sim_nbg_unify 文件夾中找到network_binary.nb模型文件。
pegasus export ovxlib --model best-sim.json --model-data best-sim.data --dtype quantized --model-quantize best-sim.quantize --batch-size 1 --save-fused-graph --target-ide-project 'linux64' --with-input-meta best-sim_inputmeta.yml --output-path ovxilb/100ask-best-sim/100ask-simprj --pack-nbg-unify --postprocess-file best-sim_postprocessmeta.yml --optimize "VIP9000PICO_PID0XEE" --viv-sdk ${VIV_SDK}
可以進(jìn)入下圖所示目錄中將network_binary.nb模型文件拷貝出來(lái)備用。
端側(cè)部署
這里引用上一篇《100ASK-V853-PRO開(kāi)發(fā)板支持yolov5模型部署》我們編寫的yolov5端側(cè)部署程序,這里進(jìn)入端側(cè)部署程序文件夾中拷貝一份新程序進(jìn)行修改。主要修改vnn_post_process.cpp程序。
修改draw_objects函數(shù)中的類名,這里我訓(xùn)練的模型的類別分別是T113、K510、V853。
類別名稱需要yolov5-6.0項(xiàng)目data目錄下data.yaml對(duì)應(yīng)。
修改generate_proposals函數(shù)中的類類別數(shù)量為您類別數(shù)量。假設(shè)我訓(xùn)練的類別總共有T113、K510、V853,這3個(gè)類別,修改為3即可。
修改后的文件如下所示:
book@100ask:~/workspaces/tina-v853-open$ source build/envsetup.sh ... book@100ask:~/workspaces/tina-v853-open$ lunch ...1 ...
進(jìn)入menuconfig,輸入
make menuconfig
進(jìn)入如下目錄中,選中yolov5-100ask配置,
> 100ask > NPU <*> yolov5-100ask......................................... yolov5-100ask demo
編譯并生成鏡像
book@100ask:~/workspaces/tina-v853-open$ make ... book@100ask:~/workspaces/tina-v853-open$ pack
編譯完成后使用全志燒寫工具燒錄鏡像。
在主機(jī)端傳入640*640的圖像文件和network_binary.nb模型文件
book@100ask:~/workspaces/testImg$ adb push test-100ask.jpg /mnt/UDISK test-100ask.jpg: 1 file pushed. 0.6 MB/s (51039 bytes in 0.078s) book@100ask:~/workspaces/testImg$ adb push network_binary.nb /mnt/UDISK network_binary.nb: 1 file pushed. 0.7 MB/s (7409024 bytes in 10.043s)
開(kāi)發(fā)板端進(jìn)入/mnt/UDISK/目錄下
root@TinaLinux:/# cd /mnt/UDISK/ root@TinaLinux:/mnt/UDISK# ls lost+found network_binary.nb overlay test-100ask.jpg
運(yùn)行yolov5檢測(cè)程序
yolov5-100ask network_binary.nb test-100ask.jpg
執(zhí)行完成后會(huì)在當(dāng)前目錄下生成輸出文件yolov5_out.jpg
root@TinaLinux:/mnt/UDISK# ls lost+found overlay yolov5_out.jpg network_binary.nb test-100ask.jpg
在主機(jī)端拉取開(kāi)發(fā)板端的輸出圖像yolov5_out.jpg
book@100ask:~/workspaces/testImg$ adb pull /mnt/UDISK/yolov5_out.jpg ./ /mnt/UDISK/yolov5_out.jpg: 1 file pulled. 0.8 MB/s (98685 bytes in 0.116s)
檢測(cè)效果圖
本文內(nèi)容均轉(zhuǎn)載自百問(wèn)科技
-
嵌入式
+關(guān)注
關(guān)注
5059文章
18973瀏覽量
302039 -
程序
+關(guān)注
關(guān)注
116文章
3756瀏覽量
80754 -
開(kāi)發(fā)板
+關(guān)注
關(guān)注
25文章
4896瀏覽量
97059 -
模型
+關(guān)注
關(guān)注
1文章
3112瀏覽量
48660 -
數(shù)據(jù)集
+關(guān)注
關(guān)注
4文章
1200瀏覽量
24619
原文標(biāo)題:我訓(xùn)練了一個(gè)模型,讓開(kāi)發(fā)板認(rèn)識(shí)自己
文章出處:【微信號(hào):gh_79acfa3aa3e3,微信公眾號(hào):全志在線】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論