记录一次推理精度退化问题的解决
作者:昇腾论坛 - sjyzzgbj
1 前言
这段时间尝试在Atlas 200 DK上开发行人重识别推理应用(本文接下来的内容也以此行人重识别推理应用为研究对象展开),期间发现模型的推理会出现严重的精度退化(mAP只有百分之零点几)。为了定位问题所在,查阅了一些资料,初步形成了一个基本有效的解决流程。现记录在此,希望能给遇到类似问题的人一点参考
2 推理应用开发流程
在介绍具体内容之前,首先介绍一下推理应用开发流程(此处结合自己的理解简要介绍,详细开发资料请见参考资料[1]:
- 准备开发环境
- 本文硬件环境:搭载昇腾310 NPU芯片的Atlas 200 DK作为硬件环境
- Atlas 200 DK环境搭建请见参考资料[2]
- 本文软件环境:Ubuntu 18.04.6 LTS;CANN Toolkit社区版6.0.RC1.alpha005
- CANN Toolkit的安装请见参考资料[3]。需要注意的是,Atlas 200 DK配套的CANN Toolkit没有商用版,只能使用社区版(理论上兼容性和稳定性都比商用版差些,但没得选)
- CANN的社区版文档在发布一段时间后会清退,此时可以使用对应的商用版文档代替(商用版文档不会被清退,比如社区版6.0.RC1.alpha005对应商用版6.0.RC1)
- 有的资料还将环境划分为分设(开发环境和运行环境不在同一台机器)和合设(开发环境和运行环境在同一台机器,本文属于此类)
- 开发场景分析
- 参考官方样例,若有相似的可作为开发基础
- 开发应用,主要包括三个阶段的逻辑:
- 资源准备阶段:运行管理资源申请、模型加载、开辟输入输出内存等
- 迭代阶段:一般包括数据预处理、填充输入内存、执行推理、读取输出内存等
- 后处理阶段:视任务需要可有可无。对于本文开发的行人重识别应用,后处理主要就是计算mAP和CMC指标
- 运行应用
3 模型导出和转换
昇腾NPU上的模型推理需要使用OM模型。具体来说,需要先将已训练的PyTorch模型导出为ONNX模型,再使用昇腾提供的ATC工具将ONNX模型转换为OM模型,步骤如下:
使用torch.onnx.export导出ONNX模型
- 该API的工作原理是使用模拟输入(第二个参数)在模型(第一个参数)上进行推理,记录计算图路径,再导出。因此,如果输入中除了Tensor之外还有和执行路径有关的参数(比如需要设置为
True还是False的标志位等。这常见于训练模型和推理模型不一致的场景,比如互学习、集成学习等),需要和Tensor一起组成元组传入,比如(dummy_input, True)。这种方式可以去除模型中的冗余分支,只保留必要的推理路径 - 更多信息请见参考资料[5]
使用昇腾ATC(Ascend Tensor Compiler,即昇腾张量编译器,用于模型转换)工具将ONNX模型转换为OM模型,命令如下:
其中,
--framework=5表示输入的模型格式为ONNX
--input_shape="输入节点名称:N,C,H,W"中的输入节点名称可以通过Netron工具可视化ONNX模型获知,比如images;N,C,H,W表示输入的shape,比如1,3,128,256表示输入shape为$1 \times 3 \times 256 \times 128$
--soc_version="芯片型号"参数十分重要,需要根据实际硬件设置,比如本文的实验中指定该参数为Ascend 310
4 推理精度测试
使用PyTorch模型、ONNX模型、OM模型分别在GPU上、CPU上、NPU上进行精度测试,结果如下:
可以看到ONNX模型精度相对PyTorch略有降低,但是降幅在2%以内,工程上可以接受,但是OM模型精度非常低,只有百分之零点几,显然出现了严重的精度退化,需要进行问题定位并解决
5 AIT工具介绍
首先,介绍一下进行推理精度问题定位所使用的AIT工具
AIT的全称是Ascend Inference Tools,即昇腾推理工具箱,包含多种推理开发中会用到精度调优、性能调优工具,本文会涉及到其中debug工具的compare功能。该功能可以在模型(支持TensorFlow、ONNX、Caffe模型)之间进行精度比对,找出精度出现差异的算子,定位问题算子所在(详细信息请见参考资料[7])
本文后续实验为了找出OM模型中的精度退化算子,对比了OM模型和ONNX模型各对应算子的精度,对比的基本原理如下:
对ONNX模型进行修改,在每个节点后面插入一个输出节点,修改前后的ONNX模型如图所示(右侧红框表示新插入的输出节点)

- 猜测对OM模型应该也进行了类似操作,但是没有找到资料佐证
使用相同的输入(可以是随机数据,也可以自定义数据)对ONNX模型和OM模型进行推理,并记录每个节点的输出值
使用多种指标衡量不同模型对应算子输出值间的相似度,比如余弦相似度、KL散度等
按输入端到输出端的顺序查看指标(因为后面的精度问题可能是由前面的精度问题导致,所以采用从前到后的顺序),对于指标超过阈值的算子,认为存在精度退化问题,具体问题具体分析进行解决。指标阈值如下:
6 推理精度问题定位和解决
本小节会涉及ATC工具的高级使用方式,请见参考资料[6]
使用AIT比较ONNX模型和OM模型,结果如图所示:

可知,第174号算子存在溢出问题,这是因为ATC工具会将模型转换为FP16,而FP16的表示范围比训练时采用的FP32小很多。此时可以尝试在ATC转换模型时强制设定174号算子的计算方式为FP32以进行算子精度保持:
其中,--keep_dtype "config.ini"表示将config.ini文件中设定的算子进行精度保持,config.ini文件内容如下:
进行精度测试,结果如下:
显然还是存在精度退化问题,实验继续进行
使用AIT比较ONNX模型和进行算子精度保持的OM模型,结果如图所示:

可知,第176号算子存在精度退化(CosineSimilarity < 0.99)。又从名字可知,这是一个融合算子,因此合理猜测精度退化可能是由于算子融合导致的。通过Netron查看OM模型中该算子的pass_name属性可知,此处算子融合匹配到的规则是TbeReduceElemwiseFusionPass,如图所示

此时可以尝试在ATC转换模型时关闭对应的算子融合规则以进行算子融合优化(同时,之前进行的算子精度保持也需要保留):
其中,--fusion_switch_file "config.cfg"表示按config.cfg文件中设定的规则进行算子融合(ATC工具已经内置了不少默认的算子融合策略,通过--fusion_switch_file "config.cfg"设定的融合策略优先级更高),config.cfg文件内容如下:
再次进行精度测试,结果如下:
可知,精度退化问题解决
(可选)使用AIT比较ONNX模型和进行算子精度保持+算子融合优化的OM模型,结果如图所示:

如果按照上面给出的阈值范围,第185号算子仍存在精度退化问题(CosineSimilarity为0.312404,小于0.99),但是实验结果又显示精度已经对齐。实际上这种情况经常出现,特别是当算子靠近输出端时(第185号算子就属此类情况),所以实际问题是否解决的判定还是需要靠端到端的精度测试实验
7 总结
- 本文给出了一种精度退化问题的解决方式:使用AIT工具对比OM模型和标杆模型(ONNX或其他格式模型)找出精度退化算子 --> 尝试解决 --> 进行精度测试实验。以上过程循环进行,直到OM模型精度和标杆模型对齐
- 希望本帖能对大家提供一点参考,也希望昇腾能不断完善推理应用开发工具集,提供更好的使用体验
- 实验中涉及到的所有文件请在提取码:8q2k下载
8 参考资料
[1] 学习向导-应用开发 (Python)-推理应用开发-...-文档首页-昇腾社区 (hiascend.com)
[2] 简介-环境部署-1.0.13-Atlas 200 DK开发者套件-文档首页-昇腾社区 (hiascend.com)
[3] 安装须知-软件安装-环境准备-...-文档首页-昇腾社区 (hiascend.com)
[4] inference/modelInference · Ascend/samples - 码云 - 开源中国 (gitee.com)
[5] TorchScript-based ONNX Exporter — PyTorch 2.2 documentation
[6] 前言-ATC模型转换-推理应用开发-...-文档首页-昇腾社区 (hiascend.com)
[7] ait: 统一推理工具链入口,提供客户一体化开发工具,支持一站式调试调优 - Gitee.com
记录一次推理精度退化问题的解决
作者:昇腾论坛 - sjyzzgbj
1 前言
这段时间尝试在Atlas 200 DK上开发行人重识别推理应用(本文接下来的内容也以此行人重识别推理应用为研究对象展开),期间发现模型的推理会出现严重的精度退化(mAP只有百分之零点几)。为了定位问题所在,查阅了一些资料,初步形成了一个基本有效的解决流程。现记录在此,希望能给遇到类似问题的人一点参考
2 推理应用开发流程
在介绍具体内容之前,首先介绍一下推理应用开发流程(此处结合自己的理解简要介绍,详细开发资料请见参考资料[1]:
3 模型导出和转换
昇腾NPU上的模型推理需要使用OM模型。具体来说,需要先将已训练的PyTorch模型导出为ONNX模型,再使用昇腾提供的ATC工具将ONNX模型转换为OM模型,步骤如下:
使用
torch.onnx.export导出ONNX模型True还是False的标志位等。这常见于训练模型和推理模型不一致的场景,比如互学习、集成学习等),需要和Tensor一起组成元组传入,比如(dummy_input, True)。这种方式可以去除模型中的冗余分支,只保留必要的推理路径使用昇腾ATC(Ascend Tensor Compiler,即昇腾张量编译器,用于模型转换)工具将ONNX模型转换为OM模型,命令如下:
其中,
--framework=5表示输入的模型格式为ONNX--input_shape="输入节点名称:N,C,H,W"中的输入节点名称可以通过Netron工具可视化ONNX模型获知,比如images;N,C,H,W表示输入的shape,比如1,3,128,256表示输入shape为$1 \times 3 \times 256 \times 128$--soc_version="芯片型号"参数十分重要,需要根据实际硬件设置,比如本文的实验中指定该参数为Ascend 3104 推理精度测试
使用PyTorch模型、ONNX模型、OM模型分别在GPU上、CPU上、NPU上进行精度测试,结果如下:
可以看到ONNX模型精度相对PyTorch略有降低,但是降幅在2%以内,工程上可以接受,但是OM模型精度非常低,只有百分之零点几,显然出现了严重的精度退化,需要进行问题定位并解决
5 AIT工具介绍
首先,介绍一下进行推理精度问题定位所使用的AIT工具
AIT的全称是Ascend Inference Tools,即昇腾推理工具箱,包含多种推理开发中会用到精度调优、性能调优工具,本文会涉及到其中debug工具的compare功能。该功能可以在模型(支持TensorFlow、ONNX、Caffe模型)之间进行精度比对,找出精度出现差异的算子,定位问题算子所在(详细信息请见参考资料[7])
本文后续实验为了找出OM模型中的精度退化算子,对比了OM模型和ONNX模型各对应算子的精度,对比的基本原理如下:
对ONNX模型进行修改,在每个节点后面插入一个输出节点,修改前后的ONNX模型如图所示(右侧红框表示新插入的输出节点)
使用相同的输入(可以是随机数据,也可以自定义数据)对ONNX模型和OM模型进行推理,并记录每个节点的输出值
使用多种指标衡量不同模型对应算子输出值间的相似度,比如余弦相似度、KL散度等
按输入端到输出端的顺序查看指标(因为后面的精度问题可能是由前面的精度问题导致,所以采用从前到后的顺序),对于指标超过阈值的算子,认为存在精度退化问题,具体问题具体分析进行解决。指标阈值如下:
6 推理精度问题定位和解决
使用AIT比较ONNX模型和OM模型,结果如图所示:
可知,第174号算子存在溢出问题,这是因为ATC工具会将模型转换为FP16,而FP16的表示范围比训练时采用的FP32小很多。此时可以尝试在ATC转换模型时强制设定174号算子的计算方式为FP32以进行算子精度保持:
其中,
--keep_dtype "config.ini"表示将config.ini文件中设定的算子进行精度保持,config.ini文件内容如下:进行精度测试,结果如下:
显然还是存在精度退化问题,实验继续进行
使用AIT比较ONNX模型和进行算子精度保持的OM模型,结果如图所示:
可知,第176号算子存在精度退化(CosineSimilarity < 0.99)。又从名字可知,这是一个融合算子,因此合理猜测精度退化可能是由于算子融合导致的。通过Netron查看OM模型中该算子的pass_name属性可知,此处算子融合匹配到的规则是
TbeReduceElemwiseFusionPass,如图所示此时可以尝试在ATC转换模型时关闭对应的算子融合规则以进行算子融合优化(同时,之前进行的算子精度保持也需要保留):
其中,
--fusion_switch_file "config.cfg"表示按config.cfg文件中设定的规则进行算子融合(ATC工具已经内置了不少默认的算子融合策略,通过--fusion_switch_file "config.cfg"设定的融合策略优先级更高),config.cfg文件内容如下:再次进行精度测试,结果如下:
可知,精度退化问题解决
(可选)使用AIT比较ONNX模型和进行算子精度保持+算子融合优化的OM模型,结果如图所示:
如果按照上面给出的阈值范围,第185号算子仍存在精度退化问题(CosineSimilarity为0.312404,小于0.99),但是实验结果又显示精度已经对齐。实际上这种情况经常出现,特别是当算子靠近输出端时(第185号算子就属此类情况),所以实际问题是否解决的判定还是需要靠端到端的精度测试实验
7 总结
8 参考资料
[1] 学习向导-应用开发 (Python)-推理应用开发-...-文档首页-昇腾社区 (hiascend.com)
[2] 简介-环境部署-1.0.13-Atlas 200 DK开发者套件-文档首页-昇腾社区 (hiascend.com)
[3] 安装须知-软件安装-环境准备-...-文档首页-昇腾社区 (hiascend.com)
[4] inference/modelInference · Ascend/samples - 码云 - 开源中国 (gitee.com)
[5] TorchScript-based ONNX Exporter — PyTorch 2.2 documentation
[6] 前言-ATC模型转换-推理应用开发-...-文档首页-昇腾社区 (hiascend.com)
[7] ait: 统一推理工具链入口,提供客户一体化开发工具,支持一站式调试调优 - Gitee.com