YOLOv3 实战完整示例
此文档使用 ENNP SDK 将 YOLOv3 移植到 EIC7700 内部的硬件加速模块实现使用 NPU 推理神经网络模型, 请在参考此文档前请先按照 ENNP SDK 下载,EsQuant 安装, EsAAC 与 EsSimulator 工具安装 配置所需环境。
此文档在 x86 ubuntu22.04 Linux 6.8.0-52-generic 上测试通过
模型转换
ONNX 模型导出
-
在 GitHub 下载官方代码
git clone https://github.com/ultralytics/yolov3.git
-
修改依赖版本 将 torch 版本指定为 1.12.0, 将 torchvision 版本指定为 0.13.0, 去掉 onnx 和 onnx-simplifier 的注释
vim requirements.txt
torch==1.12.0
torchvision==0.13.0
onnx>=1.10.0
onnx-simplifier>=0.4.1 -
安装依赖
cd yolov3
pip3 install -r requirements.txt -
下载官方模型
wget https://github.com/ultralytics/yolov3/releases/download/v9.6.0/yolov3.pt
-
导出 onnx
python3 export.py --weights ./yolov3.pt --img-size 416 --simplify --opset 13 --include onnx
模型裁减
由于导出的模型包含部分后处理操作,且量化工具暂时不支持后处理操作,所以需要裁剪掉后处理部分。 注 意裁剪部分为 conv 后的 operations。 通过 netron 查看后在裁剪脚本填写 input_names 和输出的 output_names 即可。
- onnx::Shape_406
- onnx::Shape_461
- onnx::Reshape_516
运行此 python 脚本后在当前目录生成已经剪裁后的
import onnx
input_onnx = "yolov3.onnx"
input_names = ["images"]
output_names = ["onnx::Shape_406", "onnx::Shape_461", "onnx::Reshape_516"]
output_onnx = input_onnx
cut_suffix = "_sim_extract_416_notranspose_noreshape." + input_onnx.split('.')[-1]
new_output_onnx = output_onnx.replace(".onnx", cut_suffix)
print(new_output_onnx)
onnx.utils.extract_model(input_onnx, new_output_onnx, input_names, output_names)yolov3_sim_extract_416_notranspose_noreshape.onnx
模型
模型量化
使用 EsQuant 工具执行量化模型, 请在 EsQuant Docker 中完成,具体请参考 EsQuant 模型量换工具
-
配置 config.json
config.json 已经提供在
nn-tools/sample/yolov3/esquant
里以下为示例,用户请参考并按实际情况做修改{
"version": "1.3",
"model": {
"model_path": "/workspace/yolov3_sim_extract_416_notranspose_noreshape.onnx",
"save_path": "/workspace/yolov3/",
"images_list": "/workspace/img_list.txt",
"analysis_list": "/workspace/alys_list.txt"
},
"quant": {
"quantized_method": "per_channel",
"quantized_dtype": "int8",
"requant_mode": "mean",
"quantized_algorithm": "at_eic",
"optimization_option": "auto",
"bias_option": "absmax",
"nodes_option1": [],
"nodes_option2": [],
"nodes_i8": [],
"nodes_i16": [],
"mean": [
0,0,0
],
"std": [
1,1,1
],
"norm": true,
"scale_path": "",
"enable_analyse": true,
"device": "cpu"
},
"preprocess": {
"input_format": "RGB",
"keep_ratio":false,
"resize_shape": [
416,
416
],
"crop_shape": [
416,
416
]
}
} -
在 EsQuant Docker 容中 下载 coco2017 数据集
模型量化需要校准集合, 这里使用 coco2017-1000 数据集合进行校准,请用户自行下载, 并参考
nn-tools/sample/yolov3/esquant
制作好img_list.txt
和alys_list.txt
。-
img_list.txt
/workspace/coco/val2017_1000/000000095069.jpg
/workspace/coco/val2017_1000/000000499313.jpg
/workspace/coco/val2017_1000/000000579893.jpg
/workspace/coco/val2017_1000/000000023230.jpg
/workspace/coco/val2017_1000/000000162035.jpg
... -
alys_list.txt
/workspace/coco/val2017_1000/000000095069.jpg
-
-
执行量化
python3 Example_with_config.py --config_path ./config.json --preprocess_name Yolo
量化执行完成后,进入 config.json 文件中定义的
save_path
目录,可看到生成的workspace_yolov3_sim_extract_416_notranspose_noreshape.json
文件,进行图融合后的 onnx 文件和精度分析结果文件precision_accumulate_result.txt
、precision_reset_result.txt
。 -
(可选) 量化模型精度分析
精度分析依赖于量化过程中生成的
precision_accumulate_result.txt
和precision_reset_result.txt
文件。precision_accumulate_result.txt
统计的信息为量化模型和浮点数模型逐层累计的余弦相似度误差;precision_reset_result.txt
统计的信息为量化模型和浮点数模型每层均重置输入获得的余弦相似度误差。Sigmoid_240: 0.987436056137085
Mul_241 : 0.9122292399406433
Conv_242 : 0.9125502705574036
Sigmoid_243: 0.9889860153198242
Mul_244 : 0.9188247919082642
Conv_245 : 0.8988267183303833
Sigmoid_246: 0.9783140420913696
Mul_247 : 0.9119919538497925
Conv_248 : 0.997031569480896首先查看
precision_accumulate_result.txt
中最后的 op-name(网络结构中最后一层 operation 名称)对应的 cos_dist(mean) 是否大于 95%,如果满足大于阈值则视为误差在可接受范围内。 如不满足需要查看另外一个文件即 precision_reset_result.txt。此时需要定位哪一层精度损失下降明显,然后在配置文件 config.json 中将此层替换成 int16(不要更换第一层 operation 和最后输出的 operation 的 datatype)。 操作即在配置文件中找到 nodes_int16,在其中填写 node-name 字段。重新量化并开展精度分析,再排查量化精度误差。该过程结束后一般都可以获得较高的精度,如果精度还是低于阈值,则需要排查配置参数是否正确。