当前位置: 首页 > news >正文

昇腾平台小模型推理精度问题分析方法论

作者​:昇腾实战派
知识地图​:https://blog.csdn.net/Lumos_Lovegood/article/details/161601003

背景概述

随着AI应用场景的多样化发展,开发者常需将已在GPU或CPU上训练好的小模型迁移至昇腾NPU上进行推理部署。然而,由于不同硬件平台在算子实现、数据类型支持等方面的差异,模型迁移后可能出现精度下降的问题。本文系统性地介绍了一套从整体输出比对到逐算子排查的精度定位方法论,并提供了常见精度问题的解决方案,帮助开发者高效完成模型迁移与精度调优。

1. 定位方法论

小模型精度的定位流程如下图所示。首先,在相同输入下对比GPU/CPU与NPU的输出tensor,若余弦相似度≥0.999且最大绝对误差≤0.001,则认为精度达标;否则进入精度排查步骤。排查时,使用msprobe工具一键dump并比对ONNX模型与OM模型中各算子的输出tensor,定位到第一个精度异常的算子,最后对该算子进行深入分析。

1.1. 模型输出tensor对比

以下脚本实现了Pth模型(CPU)、ONNX模型(CPU)和OM模型(NPU)的输出精度比对。若需使用GPU作为标杆,只需将device和providers改为cuda相关配置即可。

importargparseimportnumpyasnpimporttorchimportonnxruntimefromais_bench.infer.interfaceimportInferSessiondefpreprocess_image(img):ifimgisNone:img=np.random.randint(0,255,size=(112,112,3),dtype=np.uint8)else:img=cv2.imread(img)img=cv2.resize(img,(112,112))img=cv2.cvtColor(img,cv2.COLOR_BGR2RGB)img=np.transpose(img,(2,0,1))img=torch.from_numpy(img).unsqueeze(0).float()img.div_(255).sub_(0.5).div_(0.5)returnimgdefonnx_infer(onnx_model_path,img):session=onnxruntime.InferenceSession(onnx_model_path,providers=['CPUExecutionProvider'])input_name=session.get_inputs()[0].name model_output=session.run(None,{input_name:img.numpy()})[0]returnmodel_outputdefom_infer(model,img,device_id):session=InferSession(device_id,model_path=model)model_output=session.infer(feeds=[img.numpy()])[0]returnmodel_output@torch.no_grad()defpytorch_infer(weight,name,img):device=torch.device('cpu')model=ModelClass(...)model.load_state_dict(torch.load('model_weight.pth'),map_location=device)model.eval()feat=model(img).numpy()returnfeatdefprecision_compare(output1,output2,label1="Output1",label2="Output2"):output1_flat=output1.flatten().astype(np.float64)output2_flat=output2.flatten().astype(np.float64)cosine_similarity=np.dot(output1_flat,output2_flat)/(np.linalg.norm(output1_flat)*np.linalg.norm(output2_flat))absolute_errors=np.abs(output2_flat-output1_flat)relative_errors=absolute_errors/(np.abs(output1_flat)+1e-10)*100print(f'{label1}vs{label2}:')print(f' 余弦相似度:{cosine_similarity:.10f}')print(f' 最大绝对误差:{absolute_errors.max():.10e}')print(f' 最大相对误差(%):{relative_errors.max():.10e}')if__name__=="__main__":parser=argparse.ArgumentParser(description='ArcFace Model Precision Compare')parser.add_argument('--network',type=str,default='r50',help='backbone network')parser.add_argument('--weight',type=str,default='',help='PyTorch权重路径')parser.add_argument('--onnx',type=str,default=None,help='ONNX模型路径')parser.add_argument('--img',type=str,default=None,help='图片路径')parser.add_argument('--model',type=str,default=None,help='OM模型路径')parser.add_argument('--device',type=int,default=0,help='NPU device ID')args=parser.parse_args()img=preprocess_image(args.img)outputs={}ifargs.weight:outputs['PyTorch']=pytorch_infer(args.weight,args.network,img)ifargs.onnx:outputs['ONNX']=onnx_infer(args.onnx,img)print(f"ONNX output shape:{outputs['ONNX'].shape}")ifargs.model:outputs['OM']=om_infer(args.model,img,args.device)print(f"OM output shape:{outputs['OM'].shape}")if'PyTorch'inoutputsand'ONNX'inoutputs:precision_compare(outputs['PyTorch'],outputs['ONNX'],'PyTorch','ONNX')if'ONNX'inoutputsand'OM'inoutputs:precision_compare(outputs['ONNX'],outputs['OM'],'ONNX','OM')if'PyTorch'inoutputsand'OM'inoutputs:precision_compare(outputs['PyTorch'],outputs['OM'],'PyTorch','OM')

使用步骤:

  1. 数据预处理:可使用numpy生成固定随机值,或对同一张图片进行预处理得到tensor。

  2. 分别加载Pth、ONNX和OM模型进行推理,保存输出结果。

  3. 两两对比输出tensor,输出余弦相似度、最大绝对误差和最大相对误差,如下图所示:

  4. 若余弦相似度≥0.999,则认为精度达标;否则进入后续排查步骤。

1.2. 精度数据dump和对比

使用msprobe工具可一键dump并对比ONNX模型与OM模型中各算子的输出精度(工具下载地址)。命令如下:

msprobe compare-moffline_model-gp/golden_path/golden_model.onnx-tp/target_path/target_path.om-o./compare_output--input_shape"input_name:1,3,112,112"

参数说明:

  • -m:比对模式,需指定为offline_model。
  • -gp:标杆模型文件(.onnx)路径。
  • -tp:对比的昇腾AI处理器离线模型(.om)路径。
  • -o:结果输出路径,默认为当前路径的output文件夹。
  • -input_shape:模型输入为静态shape时使用,例如"input_name1:1,224,224,3;input_name2:3,300",节点间用英文分号隔开。

更多用法详见链接。

1.3. 比对结果说明及分析

输出结果文件目录结构如下:

{output_path}/{timestamp}/{input_name-input_shape} # {input_name-input_shape}用来区分动态shape时不同的模型实际输入,静态shape时没有该层 ├-- dump_data │ ├-- npu # npu dump数据目录 │ │ ├-- {timestamp} # 模型所有npu dump的算子输出,dump为False情况下没有该目录 │ │ │ └-- 0 # Rank设备ID号 │ │ │ └-- {om_model_name} # 模型名称 │ │ │ └-- 1 # 模型ID号 │ │ │ ├-- 0 # 针对每个Task ID执行的次数维护一个序号,从0开始计数,该Task每dump一次数据,序号递增1 │ │ │ │ ├-- Add.8.5.1682067845380164 │ │ │ │ ├-- ... │ │ │ │ └-- Transpose.4.1682148295048447 │ │ │ └-- 1 │ │ │ ├-- Add.11.4.1682148323212422 │ │ │ ├-- ... │ │ │ └-- Transpose.4.1682148327390978 │ │ ├-- {timestamp} │ │ │ ├-- output_0.bin │ │ │ └-- output_0.npy │ │ └-- {timestamp}_summary.json │ └-- {onnx} # 原模型dump数据存放路径,onnx对应ONNX模型 │ ├-- Add_100.0.1682148256368588.npy │ ├-- input_Add_100.0.1682148256368588.npy # 如果是ONNX模型,则会dump输入数据,并增加对应的input前缀 │ ├-- ... │ └-- Where_22.0.1682148253575249.npy ├-- input │ └-- input_0.bin # 随机输入数据,若指定了输入数据,则该文件不存在 ├-- model │ ├-- {om_model_name}.json # 离线模型OM模型(.om)通过atc工具转换后的json文件 │ └-- new_{onnx_model_name}.onnx # 把每个算子作为输出节点后新生成的ONNX模型 └-- result_{timestamp}.csv # 比对结果文件

比对结果位于result_{timestamp}.csv中,示例如下:

需关注以下字段:

  • DateType:NPU侧与CPU/GPU侧的数据类型,若不同可能存在精度损失。
  • IsNpuOps:是否为NPU独有节点,无需关注。
  • IsPrecisionError:是否为精度异常节点,需重点关注第一个精度异常的节点。
  • CosineSimilarity…MeanRelativeError:各类误差比对结果,若某项超过阈值则需重点关注。各算法说明见链接。

精度指标参考标准如下:

误差对比算法正常参考标准
CosineSimilarity> 0.99
RelativeEuclideanDistance< 0.05
KullbackLeiblerDivergence< 0.005
RootMeanSquareError< 1.0
MeanRelativeError< 1.0

根据比对结果找到第一个精度异常的算子,进行进一步分析。对于小模型,精度问题通常由数据类型强制转换导致的数值溢出引起,因为ATC在转换模型时可能强制转换某些算子的数据类型。

2. 常见精度问题解决方法

2.1. 设置精度模式

对于Atlas 800I A2或Atlas 800I A3产品,因其支持fp32数据格式,可通过ATC转换命令中的--precision_mode参数设置精度模式,避免数值溢出。例如,must_keep_origin_dtype表示保持原图精度,转换原则如下:

  • 若AI Core支持原图中算子的精度,则采用该算子。
  • 若原图算子为float16,AI Core不支持float16但支持float32和bfloat16,则自动采用高精度float32。
  • 若原图算子为float16,AI Core仅支持bfloat16,则使用float16的AI CPU算子;若AI CPU也不支持,则报错。
  • 若原图算子为float32,AI Core不支持float32仅支持float16,则使用float32的AI CPU算子;若AI CPU也不支持,则报错。

其他参数取值介绍见链接。

用法示例:

--precision_mode=must_keep_origin_dtype

不同精度模式的精度与性能排序如下:

  • 精度高低:force_fp32 > must_keep_origin_dtype > allow_fp32_to_fp16 > allow_mix_precision > force_fp16
  • 性能优劣:force_fp16 >= allow_mix_precision > allow_fp32_to_fp16 > must_keep_origin_dtype > force_fp32

2.2. 算子修改

对于部分产品,许多算子的输入输出仅支持fp16,而原始ONNX算子通常为fp32,转换过程中存在fp32到fp16的转换,容易导致数值溢出。针对此类算子精度问题,需在算子侧进行修改,具体方法因算子而异。

以conv2d算子为例,若其输入输出仅支持fp16,而原始模型基于fp32训练,卷积计算所得数值可能超出fp16范围。可通过缩放方式解决:将卷积权重(或输入)缩小x倍,由于卷积为线性操作,输出结果相应缩小x倍,从而将结果限制在fp16范围内。卷积计算完成后,将输出cast回fp32,再添加一个Mul算子将结果放大x倍。x的具体数值需根据模型实际情况确定

http://www.jsqmd.com/news/1324022/

相关文章:

  • Wi-Fi天线怎么选?5dBi全向与9dBi定向天线实测对比与选型指南
  • 企业网络安全防护与渗透测试合规指南
  • 2026年8月大连市移动100M单宽带怎么选_办理时要注意哪些关键细节_ - 找卡家园
  • Matplotlib黑白学术图表绘制:从原理到实践的全流程指南
  • URP热扭曲特效:解决半透明物体渲染难题的实战方案
  • Codex 个人用很香,为什么团队接入后反而拖了后腿?
  • 道路病害基础设施损坏标线标志牌褪色检测数据集4083张VOC+YOLO
  • 2027最新:知网 AIGC 检测怎么降到 10% 以下?(附真实报告对比与手改套路)
  • Oracle 19c与PL/SQL Developer安装配置全攻略:从零搭建企业级数据库环境
  • 如何在电脑上免费畅玩Switch游戏:yuzu模拟器终极配置指南
  • VMware安装CentOS 7全攻略:从虚拟机配置到root密码管理
  • AI生成漫画避坑指南(97%新手踩过的8个致命错误)
  • 2026年8月山东省电信300M单宽带攻略与避坑指南 - 找卡家园
  • 一篇搞懂 Linux 交换空间、Firewalld 区域规则、端口转发与安全加固
  • 2026年度优选:广西河东智能批发商找哪家——森景晟工贸专业解读 - 装修教育财税推荐2026
  • 2026年8月省市移动200M单宽带避坑与办理指南 - 找卡家园
  • Agentic AI:为什么团队接了Demo,效率反而更慢?
  • 零成本部署GLM-5.1代码大模型:Modal Serverless实战与VS Code集成指南
  • 功率同步控制在并网变流器中的稳定性分析与优化
  • 终极指南:Wand-Enhancer 完整解锁专业版功能与远程控制
  • 2027最新:维普 AIGC 检测算法升级应对教程(相似度+AI 率双降手改实例)
  • 国内实力强的GEO搜索推广推广公司最新排名榜单:精选 - 品牌推广大师
  • 明日方舟自动化基建管理工具:Arknights-Mower 终极使用指南
  • 一个回答需要10分钟:飞书问答机器人踩坑实录——纯Agent自由检索,差点让我们的机器人“难产”
  • AI安全纵深防御:从对抗样本到数据投毒的实战防护体系
  • 基于企业微信与go-cqhttp构建AI数字分身:IM生态集成实践
  • 智慧园区AR导览和传统电子屏比哪个好
  • 古式建筑物缺陷检测数据集2263张VOC+YOLO格式
  • TC389 MCMCAN模块深度解析:从CAN FD配置到实战优化
  • 2026年8月建设工程施工/建设工程施工改造管理公司口碑排行_靖昌建工集团有限公司 - 品牌宣传支持者