自定义深度学习模型的转换、编译及部署流程,使用了三种不同的编译工具:TIDL Importer,Edge AI Studio,EdgeAI-TIDL-Tools
TI文档中对yolo、mobilenet、resnet等主流深度学习模型支持十分完善,相关开箱即用的文件在 Modelzoo 中,但有关自定义模型的编译和部署内容很少,只能利用例程和提供的工具进行尝试。
深度学习模型基于TI板端运行要有几个组件:
- model:这个目录包含了要进行推理的模型(.onnx, *.prototxt)
- artifacts:这个目录包含了模型编译后生成的文件。这些文件可以用Edge AI TIDL Tools来生成和验证
- param.yaml:配置文件,提供了模型的基本信息,以及相关的预处理和后处理参数
- *dataset.yaml:配置文件,说明了用于模型训练的数据集的细节
- *run.log:这是模型的运行日志
edgeai-benchmark: Custom model benchmark can also be easily done (please refer to the documentation and example).
Uses edgeai-tidl-tools for model compilation and inference
网络结构的修改与适配
edgeai-tidl-tools与edge ai studio的编译结果可以结合onnx模型在arm上运行,因此可以有不支持的网络层(有性能损失),但若使用TIDL Importer编译,则只能转换完全支持TIDL的网络结构,因此前期将网络中不支持的层替换是最好的,
此处以YOLOX的Backbone为例,修改不支持的层:slice, Resize_206, Resize_229(resize在version13不支持,11支持), MaxPool(在11只支持kernel sizes: 3x3,2x2,1x1)
TIDL支持的算子见:supported_ops_rts_versions
ONNX算子版本见:onnx/docs/Operators
TIDL Layer Type | ONNX Ops | TFLite Ops | Notes |
---|---|---|---|
TIDL_SliceLayer | Split | NA | Only channel wise slice is supported |
TIDL_ResizeLayer | UpSample | RESIZE_NEAREST_NEIGHBOR | RESIZE_BILINEAR Only power of 2 and symmetric resize is supported |
TIDL_PoolingLayer | MaxPool, AveragePool, GlobalAveragePool | MAX_POOL_2D, AVERAGE_POOL_2D, MEAN | Pooling has been validated for the following kernel sizes: 3x3,2x2,1x1, with a maximum stride of 2 |
修改网络中三处不支持的层以支持TIDL:
1 | (1,1,256,128) --> Slice + Concat --> (1,4,128,64) |
参考TI官方对YOLOx的更改 edgeai-yolox/README_2d_od,将Slice替换为一个卷积层,再对MaxPool拆分,最后激活函数Silu替换为Relu,再重新训练,得到新模型,设为opset_version=11重新导出onnx编译后,即可只生成2个bin文件(net+io),完全的支持tidl运行加速;
ONNX模型转换及推理
使用torch.onnx.export(model, input, "XXX.onnx", verbose=False, export_params=True, opset_version=11)
得到 .onnx
;
注意要确保加载的模型是一个完整的PyTorch模型对象,而不是一个包含模型权重的字典, 否则会报错
'dict' object has no attribute 'modules'
;
因此需要在项目保存.pth
模型文件时设置同时保存网络结构,或者在项目代码中导入完整模型后使用torch.onnx.export
opset_version只支持到13,导出默认是14,会报错
opset_version为13时不支持resize, 现改为11
使用ONNX Runtime 运行推理,验证模型转换的正确性
1 | import numpy as np |
print(result)
:正常应该输出正确的推理结果,如果数值全都一样(-4.59512),可能是没有检测到有效的目标或者模型效果太差
TIDL 编译转换
得到onnx相关文件后,使用ti提供的工具进行编译和推理,这里采用三种不同的模型转换方法:
- TIDL Importer :部署于EVM板,网络结构需要全部支持TIDL
- Edgeai-tidl-tools:可部署于SK板,需要onnx运行环境,配置灵活,网络结构要求少
- Edge AI Studio:TIDL tools的在线版本
TIDL Importer
TIDL Importer 是RTOS SDK中提供的导入工具,需要网络结构完全支持tidl,以使模型都通过tidl加速(即转换只生成net,io 2个bin文件)
下面的流程重构了文件夹架构,原文件跳来跳去改起来很麻烦,就合并到了XXX文件夹,原文件路径可参考上一篇官方例程: TDA4③_使用TIDL Importer导入YOLOX
源码见:Arrowes/DMS-YOLOv8/tree/main/TI/tidl_importer/
配置文件:新建文件夹:
SDK/${TIDL_INSTALL_PATH}/ti_dl/test/testvecs/XXX
拷贝 onnx 文件至 XXX 文件夹 (此处是自定义模型,不使用prototxt, 经测试可以正常编译)1
2
3
4
5
6
7
8
9
10
11
12#XXX文件夹结构
├── detection_list.txt
├── device_configs
│ ├── am62a_config.cfg
│ ├── j721e_config.cfg
│ ├── j721s2_config.cfg
│ └── j784s4_config.cfg
├── output
├── indata
│ └── 1.jpg
├── XXX.onnx
└── tidl_import_XXX.txt编写转换配置文件:新建tidl_import_XXX.txt,可参考同目录下其他例程,详细参数配置见文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#tidl_import_XXX.txt:
modelType = 2
numParamBits = 8
numFeatureBits = 8
quantizationStyle = 3
inputNetFile = "../../test/testvecs/XXX/XXX_yolox_221_sig_11.onnx"
outputNetFile = "../../test/testvecs/XXX/output/825_tidl_net_sig_SDK8_6.bin"
outputParamsFile = "../../test/testvecs/XXX/output/825_tidl_io__sig_SDK8_6"
inDataNorm = 1
inMean = 0 0 0
inScale = 0.003921568627 0.003921568627 0.003921568627
inDataFormat = 1
inWidth = 128
inHeight = 256
inNumChannels = 3
numFrames = 50
inData = "../../test/testvecs/XXX/detection_list.txt"
perfSimConfig = ../../test/testvecs/XXX/device_configs/j721s2_config.cfg
debugTraceLevel = 1Debug:
inData
配置数据输入(回车分隔),数量与numFrames
要匹配;perfSimConfig
选择对应设备的配置文件;inScale
配置太大可能导致tensor不匹配metaLayersNamesList
注释掉, 除非与TI提供的元架构相同;执行编译,得到可执行文件
.bin
1
2
3
4
5
6
7
8
9export TIDL_INSTALL_PATH=/home/wyj/sda2/TAD4VL_SKD_8_5/ti-processor-sdk-rtos-j721s2-evm-08_05_00_11/tidl_j721s2_08_05_00_16
cd ${TIDL_INSTALL_PATH}/ti_dl/utils/tidlModelImport
./out/tidl_model_import.out ${TIDL_INSTALL_PATH}/ti_dl/test/testvecs/XXX/tidl_import_yolox.txt
#successful Memory allocation
#../../test/testvecs/XXX/output/生成的文件分析:
tidl_net_XXX.bin #Compiled network file 网络模型数据
tidl_io_XXX.bin #Compiled I/O file 网络输入配置文件
tidl_net_XXX.bin.svg #tidlModelGraphviz tool生成的网络图
tidl_out.png, tidl_out.txt #执行的目标检测测试结果TIDL运行(inference)
TI Deep Learning Library User Guide: TIDL Inference1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#在文件ti_dl/test/testvecs/config/config_list.txt顶部加入:
1 testvecs/XXX/tidl_infer_XXX.txt
0
#新建tidl_infer_yolox.txt:
inFileFormat = 2
numFrames = 10
netBinFile = "testvecs/XXX/output/825_tidl_net_sig_SDK8_6.bin"
ioConfigFile = "testvecs/XXX/output/825_tidl_io_sig_SDK8_61.bin"
inData = testvecs/XXX/detection_list.txt
outData = testvecs/XXX/infer_out/inference.bin
inResizeMode = 0
#0 : Disable, 1- Classification top 1 and 5 accuracy, 2 – Draw bounding box for OD, 3 - Pixel level color blending
postProcType = 2
debugTraceLevel = 1
writeTraceLevel = 0
writeOutput = 1
#运行,结果在ti_dl/test/testvecs/output/
cd ${TIDL_INSTALL_PATH}/ti_dl/test && ./PC_dsp_test_dl_algo.out
Edge AI Studio
参考yolox的编译过程:YOLOX的模型转换与SK板端运行,修改数据预处理与compile_options部分,最后重写画框部分(optional)
Debug:
[ONNXRuntimeError] : 6 ...
: compile_options中设置deny_list,剔除不支持的层,如'Slice'
,TIDL支持的算子见:supported_ops_rts_versions (resize支持2*操作)
compile_options中要注释掉object_detection的配置
打包下载编译生成的工件:
1 | #Pack.ipynb |
EdgeAI-TIDL-Tools
环境搭建见:TDA4②
研读 edgeai-tidl-tools/examples/osrt_python/ort/onnxrt_ep.py:
进入搭建好的环境:(例)pyenv activate benchmark
或 conda activate tidl
运行:./scripts/run_python_examples.sh
下面基于例程进行基本的修改以编译运行自定义模型, 至少需要修改四个文件,源码见:Arrowes/DMS-YOLOv8/tree/main/TI/tidl_tools
1 | #新建运行脚本./script/run.sh |
配置编译选项文档:edgeai-tidl-tools/examples/osrt_python/README.md
Debug:
有些模型下载会卡住,要到model_configs中找到链接手动下载放入models/public
'TIDLCompilationProvider' is not in available:
环境问题,没有进入配置好的环境,正常应该是:Available execution providers : ['TIDLExecutionProvider', 'TIDLCompilationProvider', 'CPUExecutionProvider']
Provider的问题可能会引发AttributeError: 'InferenceSession' object has no attribute 'get_TI_benchmark_data'
解决办法:pip uninstall onnxruntime
,pip uninstall onnxruntime-gpu
,pip uninstall onnxruntime-tidl
, 然后重新 setup.sh
onnxrt_ep.py详解
edgeai-tidl-tools/examples/osrt_python/ort/onnxrt_ep.py 是主要运行文件,也是修改的最多的部分,因此梳理此处代码有助于理解tidl编译和运行的全流程。
Debug:
其中容易出问题的是预处理部分,image size不对很容易出问题。
替换的某些测试图片读不进去导致报错,原理未知权限问题,sudo nautilus 右键属性更改读写权限
onnxrt_ep.py code
1 | import onnxruntime as rt |
model-artifacts
分析编译深度学习模型后生成的文件:
1 | └── model-artifacts #文件都是以最后的输出层命名,分为四块网络结构 |
为什么有些网络结构编译后被拆分成了多组不同的二进制文件?(4 subgraph output nodes): 多网络结构文件拼接成一个完整的网络,但由于不支持的层被offload到arm端运行,因此在相应的位置被拆分,前期网络结构设计时需要尽量避免出现该情况。
TIDL tools c++推理(ongoing)
TIDL runtime 提供的CPP api解决方案仅支持模型推理,因此仍需在PC上运行Python示例以生成模型工件。
edgeai-tidl-tools/examples/osrt_cpp
1 | export SOC=am68pa |
SK板运行自定义深度学习模型(ongoing)
通过SD卡配置编译生成的模型:
配置模型文件夹 custom_model 放入/opt/modelzoo文件夹
artifacts:存放编译生成的工件,model-artifacts
model:原onnx模型,.onnx (.prototxt)
param.yaml:配置文件, 其中需要修改model_path等参数 (以modelzoo中例程的param为基准,参照model-artifacts中生成的param修改参数)
(dataset.yaml:数据集类别对应文件)
通过SD卡配置/opt/edgeai-gst-apps/configs/XXX.yaml
,在model参数中索引上面建立的模型文件夹 custom_model, 并根据size修改输入输出,分辨率size一定要改好,否则很容易报错
1 | #通过minicom连接串口 |
如果不是常规的OD、SEG等任务,需要高度自定义的话,需要修改SK板 /opt/edgeai-gst-apps
DEMO相关的源码,主要阅读源码并参考两大文档:
Edge AI sample apps — Processor SDK Linux for SK-TDA4VM Documentation
Running Simple demos — Processor SDK Linux for Edge AI Documentation
也许可以将tidl-tools放到板子里然后运行? 然后选择正确的平台
/opt/vision_apps/vx_app_arm_remote_log.out 查arm log的脚本
YOLO-pose实例:Practicing Yoga with AI: Human Pose Estimation on the TDA4VM
官方视频:Efficient object detection using Yolov5 and TDA4x processors | Video | TI.com
官方文档:4. Deep learning models — Processor SDK Linux for SK-TDA4VM Documentation
TDA4系列文章:
TDA4①:SDK, TIDL, OpenVX
TDA4②:环境搭建、模型转换、Demo及Tools
TDA4③:YOLOX的模型转换与SK板端运行
TDA4④:部署自定义深度学习模型