我来帮你分析这个问题。先搜索一下社区是否有类似的精度差异讨论。
根据你提供的测试结果和代码,我来直接回答你的两个问题:
结论
1. Model Zoo 提供的.bin 文件不是精度最优版本?
- 不是。Model Zoo 提供的模型是经过标准 PTQ 流程转换的通用版本,精度损失在可接受范围内。
2. 板卡精度下降是否正常?
- 不正常。你的测试结果中:
- 板卡端 mAP@0.5: 0.5430
- 电脑端 mAP@0.5: 0.7079
- 精度损失达 23%,远超正常的 1-3% 范围
问题排查
根据社区官方文档《模型精度验证及调优建议》,你需要按以下步骤排查:
第一步:验证 quantized.onnx 与.bin 的一致性
使用 hb_verifier 工具验证模型转换是否正确:
hb_verifier -m quantized.onnx,yolov5m_tag_v2.0_detect_640x640_bayese_nv12.bin -b <板卡 IP> -s True
预期结果:应显示 Quanti onnx and Arm result Strict check PASSED
如果一致性验证失败,说明模型转换或编译有问题,需要重新转换。
第二步:检查前后处理代码
你的代码中有几个关键问题:
问题 1:Score 计算方式错误
你的代码中:
s_max_scores = 1 / ((1 + np.exp(-s_pred[:, 4]))*(1 + np.exp(-s_raw_max_scores)))
这个计算公式不正确。YOLOv5 的正确 score 计算应该是:
objectness = sigmoid(s_pred[:, 4]) # 目标置信度
class_scores = sigmoid(s_pred[:, 5:]) # 类别概率
s_max_scores = objectness * np.max(class_scores, axis=1) # 最终得分
问题 2:Anchor 解码公式可能不匹配
你使用的解码公式:
s_dxyhw = 1 / (1 + np.exp(-s_pred[s_valid_indices, :4]))
s_xy = (s_dxyhw[:, 0:2] * 2.0 + self.s_grid[s_valid_indices,:] - 1.0) * self.strides[0]
s_wh = (s_dxyhw[:, 2:4] * 2.0) ** 2 * self.s_anchors[s_valid_indices, :]
这是 YOLOv5 v6.0+ 的解码方式,但 Model Zoo 的 yolov5s-v2.0 应该使用 v2.0 的解码方式:
# YOLOv5 v2.0 标准解码
s_xy = (sigmoid(s_pred[:, :2]) + self.s_grid) * self.strides[0]
s_wh = (np.exp(s_pred[:, 2:4]) * self.s_anchors) * self.strides[0]
问题 3:输入数据预处理
确认你的 NV12 转换是否正确。建议使用官方推荐的方式:
# 使用 hobot_dnn 的预处理
input_tensor = cv2.resize(orig_img, (self.input_w, self.input_h))
# 不需要手动转 NV12,hobot_dnn 会自动处理
建议的排查流程
1. 先用官方示例代码测试
下载官方 Model Zoo 示例代码,直接用提供的测试脚本跑一下:
cd ~/model_zoo/yolov5
python3 test.py --model bin/yolov5s-v2.0.bin --data dataset/coco128
如果官方代码结果正常,说明是你的后处理代码有问题。
2. 使用 hb_verifier 验证
# 验证一致性
hb_verifier -m quantized.onnx,yolov5s-v2.0.bin -b <板卡 IP> -s True
# 如果失败,查看详细信息
hb_verifier -m quantized.onnx,yolov5s-v2.0.bin -b <板卡 IP> -r True
3. 对比 quantized.onnx 和.bin 的输出
在电脑端用 HB_ONNXRuntime 跑 quantized.onnx:
from horizon_tc_ui import HB_ONNXRuntime
sess = HB_ONNXRuntime(model_file="quantized.onnx")
input_names = [input.name for input in sess.get_inputs()]
output_names = [output.name for output in sess.get_outputs()]
# 准备输入(注意 input_offset=128)
feed_dict = {input_names[0]: input_data}
outputs = sess.run(output_names, feed_dict, input_offset=128)
对比 quantized.onnx 和.bin 的原始输出(后处理之前),如果差异大,说明模型转换有问题。
快速修复建议
最可能的原因是后处理代码与模型版本不匹配。建议:
- 直接使用官方后处理代码:从 Model Zoo 示例中复制后处理部分
- 或者重新训练/转换模型:使用你自己的数据集和配置重新转换,确保前后处理一致
如果需要进一步帮助,请提供:
hb_verifier的验证结果- 你使用的具体模型文件(yolov5s 还是 yolov5m?)
- 转换时使用的 yaml 配置文件
相关社区资源
- 模型精度验证及调优建议(精华帖)
- bin 模型精度下降(类似案例)
- PTQ&QAT 方案板端验证注意事项