模型转换前的准备工作
-
创建属于待转换模型的目录,避免后续转换其他模型会带来的混乱。
比如 ${模型目录} 为 ~/workspace/vivante-acuity-toolkit/yolov5nu
执行下列命令
mkdir -p ${模型目录} -
获取yolo学习笔记
git clone https://github.com/hexchip/ultralytics-nootbook.git -
启动 jupyter nootbook 容器并挂载学习笔记目录
比如 ${学习笔记目录} 为 ~/workspace/yolov8-nootbook
docker run -it \ --rm \ -p 8888:8888 \ --mount type=bind,source=${学习笔记目录},target=/workspace \ --gpus=all \ --ipc=host \ cld1994/ultralytics:8.1.26-jupyter在浏览器中打开jupyter nootbook:http://127.0.0.1:8888/lab
-
获取待转换模型的onnx格式
我们以获取yolov5nu模型的onnx格式为例
在浏览器的jupyter nootbook页面中打开 export-onnx.ipynb
执行!
执行完成后可以在左侧导航栏的根目录中发现新增的 yolov5nu.onnx
在主机命令行中执行下列命令放入${模型目录}
cp ${学习笔记目录}/yolov5nu.onnx ${模型目录} -
准备量化所需的数据集和对应的声明文件
在浏览器的jupyter nootbook页面中打开 download_coco_dataset.ipynb。
逐步执行!
执行完成后可以在左侧导航栏的根目录中的coco目录下发现新增的 preprocessed 目录
量化所需的数据集就存放在此目录
此时,你可以在你的主机中找到它,路径为 ${学习笔记目录}/coco/preprocessed同时在左侧导航栏的根目录中发现新增的dataset.txt文件,该文件即量化所需的数据集声明文件。 此时,你可以在你的主机中找到它,路径为 ${学习笔记目录}/dataset.txt
在主机命令行中执行下列命令放入量化所需的数据集和对应的声明文件
cp ${学习笔记目录}/dataset.txt ${模型目录} mkdir -p ${模型目录}/coco/train2017 cp ${学习笔记目录}/coco/preprocessed/* ${模型目录}/coco/train2017/ -
启动 acuity-toolkit 容器并挂载该模型的目录
docker run \ -it \ --rm \ --mount type=bind,source=${模型目录},target=/workspace \ cld1994/vivante-acuity-toolkit:6.6.1-ide5.7.0
模型转换
进入 acuity-toolkit 容器后执行下列命令
-
导入模型
cd /usr/local/VeriSilicon/acuity-toolkit-binary-6.6.1/bin/ pegasus import onnx --model ${模型目录}/yolov5nu.onnx该操作在${模型目录}生成了 yolov5nu.json 和 yolov5nu.data
-
为模型生成输入元数据文件
cd ${模型目录} pegasus generate inputmeta --model yolov5nu.json该操作在${模型目录}生成了 yolov5nu_inputmeta.yml
-
修改yolov5nu_inputmeta.yml 的 scale 参数 为 0.0039216
-
先推导一次,目的是与量化后的模型进行精度对比
pegasus inference \ --model yolov5nu.json \ --model-data yolov5nu.data \ --with-input-meta yolov5nu_inputmeta.yml该操作生成了两个文件, 分别代表模型的输入张量和输出张量:
- iter_0_images_267_out0_1_3_320_320.tensor
- iter_0_attach_Concat__model.24_Concat_5_out0_0_out0_1_84_2100.tensor
-
将模型进行量化
其中 --iterations 的值为 dataset.txt 的有效行数
pegasus quantize \ --model yolov5nu.json \ --model-data yolov5nu.data \ --with-input-meta yolov5nu_inputmeta.yml \ --algorithm kl_divergence \ --divergence-first-quantize-bits 11 \ --quantizer perchannel_symmetric_affine \ --qtype int8 \ --iterations 796 \ --rebuild该操作生成了量化表⽂件 yolov5nu.quantize
-
将模型进行混合量化
因yolov5nu模型包含了对特征图进行结果处理的算子(比如计算坐标,置信度等),int8量化后误差较大,还需要对这些算子进行混合量化。
打开量化表⽂件 yolov5nu.quantize,在底部的 customized_quantize_layers: 下增加这些层:
customized_quantize_layers: attach_Concat_/model.24/Concat_5/out0_0: dynamic_fixed_point-i16 Concat_/model.24/Concat_5_1: dynamic_fixed_point-i16 Mul_/model.24/Mul_2_2: dynamic_fixed_point-i16 Sigmoid_/model.24/Sigmoid_3: dynamic_fixed_point-i16 Concat_/model.24/Concat_4_4: dynamic_fixed_point-i16 Initializer_/model.24/Constant_12_output_0_5: dynamic_fixed_point-i16 Div_/model.24/Div_1_6: dynamic_fixed_point-i16 Sub_/model.24/Sub_1_7: dynamic_fixed_point-i16 Add_/model.24/Add_2_8: dynamic_fixed_point-i16 Initializer_/model.24/Constant_11_output_0_9: dynamic_fixed_point-i16 Add_/model.24/Add_1_10: dynamic_fixed_point-i16 Sub_/model.24/Sub_11: dynamic_fixed_point-i16 Slice_/model.24/Slice_12: dynamic_fixed_point-i16 Reshape_/model.24/dfl/Reshape_1_13: dynamic_fixed_point-i16 Initializer_/model.24/Constant_9_output_0_14: dynamic_fixed_point-i16 Slice_/model.24/Slice_1_15: dynamic_fixed_point-i16 Conv_/model.24/dfl/conv/Conv_17: dynamic_fixed_point-i16 Softmax_/model.24/dfl/Softmax_18: dynamic_fixed_point-i16 Reshape_/model.24/dfl/Reshape_20: dynamic_fixed_point-i16 Split_/model.24/Split_21: dynamic_fixed_point-i16 Reshape_/model.24/dfl/Reshape_1_13_acuity_mark_perm_268: dynamic_fixed_point-i16 Softmax_/model.24/dfl/Softmax_18_acuity_mark_perm_269: dynamic_fixed_point-i16然后执行下列命令进行混合量化
pegasus quantize \ --model yolov5nu.json \ --model-data yolov5nu.data \ --with-input-meta yolov5nu_inputmeta.yml \ --algorithm kl_divergence \ --divergence-first-quantize-bits 11 \ --quantizer perchannel_symmetric_affine \ --qtype int8 \ --iterations 796 \ --model-quantize yolov5nu.quantize \ --hybrid该操作生成了 yolov5nu.quantize.json文件,后续都将使用它来代替 yolov5nu.json
-
进行推理,目的是与浮点精度的推理结果作对比。
先将浮点精度下的推理结果移动到 ${学习笔记目录},在主机终端中执行下列命令:
mv ${模型目录}/iter_0_images_267_out0_1_3_320_320.tensor ${学习笔记目录}/float_input_1_3_320_320.tensor mv ${模型目录}/iter_0_attach_Concat__model.24_Concat_5_out0_0_out0_1_84_2100.tensor ${学习笔记目录}/float_result_84_2100.tensor然后在容器中执行下列代码进行推理
pegasus inference \ --model yolov5nu.quantize.json \ --model-data yolov5nu.data \ --with-input-meta yolov5nu_inputmeta.yml \ --dtype quantized \ --model-quantize yolov5nu.quantize该操作生成了两个文件, 分别代表模型的输入张量和输出张量:
- iter_0_images_267_out0_1_3_320_320.tensor
- iter_0_attach_Concat__model.24_Concat_5_out0_0_out0_1_84_2100.tensor
最后,将量化精度的推理结果移动到 ${学习笔记目录},在主机终端中执行下列命令:
mv ${模型目录}/iter_0_images_267_out0_1_3_320_320.tensor ${学习笔记目录}/input_1_3_320_320.tensor mv ${模型目录}/iter_0_attach_Concat__model.24_Concat_5_out0_0_out0_1_84_2100.tensor ${学习笔记目录}/result_84_2100.tensor -
在jupyter nootbook 容器中验证量化精度是否可用
在浏览器的jupyter nootbook页面中打开 see-result.ipynb。
逐行执行!可以看到浮点进度的推理结果在图片上的展示。
接着修改第二个单元格中的imgTensorPath,resultTensorPath变量
imgTensorPath = 'input_1_3_320_320.tensor' resultTensorPath = 'result_84_2100.tensor'点击如图所示图标,重新运行该笔记本。可以看到量化精度的推理结果在图片上的展示。
-
导出模型
在 acuity-toolkit 容器执行下列命令
cd /usr/local/VeriSilicon/acuity-toolkit-binary-6.6.1/bin/pegasus export ovxlib \ --model ${模型目录}/yolov5nu.quantize.json \ --model-data ${模型目录}/yolov5nu.data \ --with-input-meta ${模型目录}/yolov5nu_inputmeta.yml \ --dtype quantized \ --model-quantize ${模型目录}/yolov5nu.quantize \ --output-path ${模型目录}/ovxilb/yolov5nu \ --save-fused-graph \ --pack-nbg-unify \ --optimize "VIP9000PICO_PID0XEE" \ --viv-sdk ${VIV_SDK}cd ${模型目录}该步骤生成了ovxilb,ovxilb_nbg_unify 两个目录。
我们需要的模型文件路径为 ovxilb_nbg_unify/network_binary.nb
其他文件可以忽略。
-
查看模型内存占用信息
在 acuity-toolkit 容器执行下列命令
nbinfo -a ${模型目录}/ovxilb_nbg_unify/network_binary.nb
yolov5nu的迁移训练
Ultralytics官方推荐使用 Roboflow 作为数据标注平台与数据集管理平台。
注:需要科学上网
这里不详细展开说明,我们假设已经在该平台上准备好了数据集。
在浏览器的jupyter nootbook页面中打开 train.ipynb。
参考修改并执行。
注:大部分迁移训练相关的知识请看Ultralytics官方文档