两边都用 YOLOv5 v6.0 val.py 同一套口径评测同一个业务模型 shv54。
NVIDIA 侧产物是既有标准输出,Atlas 侧由 AscendDemo/scripts/eval_yolov5_style.py 生成,
6 个产物同名同规格,可以直接 diff / 并排看图。

NVIDIAAtlas 300V
产物目录docs/shv54精度数据/docs/shv54精度数据_atlas/
评测脚本YOLOv5 v6.0 val.py + utils/metrics.pyAscendDemo/scripts/eval_yolov5_style.py(复刻同一套逻辑)
评测图数 / 实例数4997 / 149754991 / 14949

1. 结论

结论依据
昇腾链路与 NVIDIA 的精度基本等价,没有出现迁移掉点逐类 P 差 ≤ 0.0030、R 差 ≤ 0.0050;mAP@0.5 反而高 +0.0080
唯一系统性差异是 mAP@0.5:.95 低 -0.0320,且只出现在高 IoU 段IoU ≤ 0.5 的所有指标(mAP@0.5、逐类 P/R、混淆矩阵)两边逐项吻合
这不是平台数值精度问题同一 ONNX 在 ONNX Runtime(FP32) 与昇腾 NPU(FP16) 上,GT 的 best-IoU 均值 0.92662 vs 0.92724(差 +0.00062)
评测口径已逐项对齐见 §2;且自研实现与上游 utils/metrics.py 做过逐位对拍(max|diff| = 0.000e+00)

一句话:这不是"昇腾比 NVIDIA 差",而是"两边在框坐标精度上差了约 3 个百分点的mAP@0.5:.95,检出/漏检/误检行为两边一致"。

2. 口径对齐(两边一致的部分)

环节取值说明
评测实现AscendDemo/scripts/eval_yolov5_style.py复刻 YOLOv5 v6.0 val.py + utils/metrics.py
金标准对拍上游 utils/metrics.py 逐位比对TP 矩阵、AP 矩阵、PR 曲线、混淆矩阵 全部 max|diff| = 0.000e+00
输入尺寸imgsz=960, rect=True本数据集 16:9 图的 rect 画布与我们的 .om 画布逐像素一致
NMSconf=0.001, iou=0.6, max_det=300(每类)与 val.py 的 non_max_suppression 一致
NMS 语义per-class(multi_label=True)原仓库 val.py:217 明确传 multi_label=True,我们的图内 NMS 语义与之相同
匹配规则同类 + IoU >= 0.5(0.5:0.95 共 10 档)+ IoU 降序贪心与上游 process_batch 一致
APnp.trapz(np.interp(101 点))与上游 compute_ap 一致
工作点smooth(f1.mean(0), 0.1).argmax()YOLOv5 的 best-F1 点
混淆矩阵conf=0.25, iou=0.45, 列归一化, <0.005 置 NaN与上游 ConfusionMatrix 一致
指标汇总宏平均resualt.txt 的 all 行是三类宏平均

3. 数据集差异(唯一的数据集层面的不对称)

Atlas 侧用的是本地 test_assets/ 4991 张带标注图;NVIDIA 侧参考产物是 4997 张。
差的 6 张图带走了 26 个标注框:

classNVIDIA 实例数Atlas 实例数差
person78057792-13
helmet38723869-3
head32983288-10
all1497514949-26

实例数差异 ≤ 0.7%。注意:这 6 张图是 NVIDIA 侧多出来的,两边的评测集并不完全相同,
逐类指标的差异里有一部分来自这里。

4. 主对比表(resualt.txt 全字段)

all 行(宏平均):

项NVIDIAAtlas 300V差值
all · Images49974991-6
all · Instances1497514949-26
all · P0.9580.959+0.0010
all · R0.9530.949-0.0040
all · mAP@.50.9710.979+0.0080
all · mAP@.5:.950.860.828-0.0320

逐类:

| class | NVIDIA P | Atlas P | ΔP | NVIDIA R | Atlas R | ΔR | NVIDIA mAP@.5 | Atlas mAP@.5 | ΔmAP | NVIDIA mAP@.5:.95 | Atlas mAP@.5:.95 | ΔmAP |
|—|—|—|—|—|—|—|—|—|—|—|—|—|—|
| person | 0.969 | 0.969 | +0.0000 | 0.966 | 0.963 | -0.0030 | 0.98 | 0.987 | +0.0070 | 0.886 | 0.86 | -0.0260 |
| helmet | 0.926 | 0.929 | +0.0030 | 0.949 | 0.948 | -0.0010 | 0.964 | 0.972 | +0.0080 | 0.834 | 0.798 | -0.0360 |
| head | 0.98 | 0.979 | -0.0010 | 0.942 | 0.937 | -0.0050 | 0.969 | 0.979 | +0.0100 | 0.859 | 0.827 | -0.0320 |

表中的数值是 resualt.txt 的原始字面值(上游 %.3g,只有 3 位有效数字),
两边格式完全相同,可以直接 diff。
差值列由这些 3 位有效数字算出;§5 给出 metrics.json 里的全精度值。

5. Atlas 侧工作点细节(best-F1,全精度)

本节数值来自 docs/shv54精度数据_atlas/metrics.json(全精度),
§4 里 resualt.txt 的 3 位有效数字就是这些值按上游 %.3g 取整后的结果。

项值
best-F1 置信度0.5145
宏平均 precision0.9590
宏平均 recall0.9490
宏平均 F10.9539
参与匹配的图片数4991
预测框总数(score ≥ 0.001)70729

逐类 TP/FP(best-F1 工作点):

classGTTPFPPRF1AP@.5AP@.5:.95
person779275012420.96870.96270.96570.98660.8595
helmet386936662800.92900.94750.93820.97200.7982
head32883081650.97930.93690.95770.97930.8272

Atlas 侧逐 IoU 档的 mAP(说明高 IoU 段是怎么塌下去的):

IoU0.500.550.600.650.700.750.800.850.900.95
mAP0.97930.97580.96910.95820.93830.90670.86050.78360.63590.2757

6. 混淆矩阵(conf=0.25, iou=0.45,列归一化,列 = GT)

GT \ 预测personhelmethead背景 FP
person0.970.030.010.48
helmet0.010.950.030.38
head0.000.010.940.14
background FN0.020.020.02—

NVIDIA 侧同口径矩阵(从 docs/shv54精度数据/confusion_matrix.png 读出):

GT \ 预测personhelmethead背景 FP
person0.97——0.42
helmet—0.950.020.45
head——0.940.13
background FN0.030.050.04—

逐项吻合:对角线 person / helmet / head 的检出率两边都是 0.97 / 0.95 / 0.94;
漏检(background FN 行)NVIDIA 0.03 / 0.05 / 0.04,Atlas 0.02 / 0.02 / 0.02;
误检构成(background FP 列)NVIDIA 0.42 / 0.45 / 0.13,Atlas 0.48 / 0.38 / 0.14。
→ 两边的检测集(检出 / 漏检 / 误检)是等价的。

7. 差异归因

7.1 已排除的原因(都有实验数据)

候选原因判别实验结果
平台数值精度(NPU FP16 vs NVIDIA FP32)同一 ONNX 跑 ORT(FP32),与 .om(FP16) 在 200 张同图上比「每个 GT 的 best-IoU」ORT 0.92662 vs .om 0.92724(差 +0.00062);坐标偏差中位数 3.18 px vs 3.00 px → 逐框等效,不是原因
NMS 的 multi-label 语义把 70729 个框按「同坐标只留最高分」折成单标签后重评丢 8382 框,mAP@0.5 0.9793→0.9786,mAP@0.5:.95 0.8283→0.8293 → Δ ≤ 0.001,不是原因
max_det 分配规则(每类 300 vs 全局 300)统计单图检测数单图总框数 > 300 的图 0 张,单类 > 300 的 0 次 → 完全没触发
输入画布(960×544 vs YOLOv5 rect 的 992×576)用 ORT 在 992×576 画布上跑同 200 张图mAP@0.5 0.9445→0.9547,但 mAP@0.5:.95 0.8254→0.8234 → 高 IoU 段没改善,不是原因
GT 标注口径(labels/*.txt vs Annotations/*.xml)同一份预测分别对两套 GT 评测txt 更优(mAP@0.5:.95 0.8283 vs XML 0.8037);两份 GT 存在系统性 1 像素偏移,但我们用的 txt 已是与模型对齐的那套 → 不是原因
NMS 的 iou_thres(0.6 vs 0.45)用 ORT 跑 iou=0.45 的 ONNX,比同 200 张图mAP@0.5:.95 0.8254→0.8237 → Δ ≤ 0.002,不是原因
评测流程本身引入的误差把生产 .om 的预测也做同样的尺寸偏差统计生产 .om 与评测 .om 的偏差数字完全一致(person 宽比中位 1.00545、高比 1.00470)→ 生产链路有同样的定位上限,不是评测流程的产物

7.2 仍未定位的差异

mAP@0.5:.95 低 0.0320,表现为 IoU 档越高差得越多:

IoU 档0.500.550.600.650.700.750.800.850.900.95
Atlas mAP0.97930.97580.96910.95820.93830.90670.86050.78360.63590.2757

Atlas 侧「每个 GT 能达到的 best-IoU」分布(这是高 IoU 段的天花板):

classbest-IoU 中位数best-IoU 均值IoU≥0.95 的 GT 占比
person0.94280.912844.2%
helmet0.92140.883329.8%
head0.92900.896329.3%

即:绝大多数 GT 只能匹配到 IoU 0.92~0.94 的框,高 IoU 档的 AP 因此天然偏低。
而 NVIDIA 侧 mAP@0.5:.95 更高,说明其框坐标精度上限更高。

重要:这不是评测链路的缺陷——生产 .om(shv54.om)的预测做同样统计,
尺寸偏差数字与评测 .om 完全一致,也就是说线上的定位精度上限是同一个。

剩下的可能来源,都在「两边跑的到底是不是同一个程序」这一层,
无法从 NVIDIA 侧的产物反推:

  1. NVIDIA 侧是逐 batch 变画布的。YOLOv5 rect 模式按每个 batch 的宽高比算 batch_shapes(utils/dataloaders.py:501),同一份数据不同 batch 的画布可以不同;
    我们只有一个固定画布 960×544。上表已验证「换成 992×576 画布」并不能改善高 IoU 段,
    但逐 batch 混合画布没有单独复现。
  2. NVIDIA 侧的具体命令行参数无法从产物反推(--iou-thres / --conf-thres / --batch-size / --rect)。产物只能反映最终数值,反映不了运行参数。
  3. 评测集不完全相同(4997 vs 4991)。但多出的 6 张图只占 0.12%,
    不足以解释 0.03 的聚合差。

结论口径:以上三点都属于「两边不是同一次运行的完全复刻」,
而不是昇腾链路的精度缺陷——从 §6 的混淆矩阵和 §4 的 P/R 看,
检测能力(检出/漏检/误检)两边等价,差异集中在框坐标精度这一层。

若要彻底闭合,需要拿到 NVIDIA 侧那次 val.py 的完整命令行与运行日志。

8. 复现步骤

# 1) 导出评测专用 ONNX(图内 NMS:conf=0.001 / iou=0.6 / 每类 300)
source .venv/bin/activate
python AscendDemo/scripts/export_yolo_onnx.py \
    --weights model/shv54_head.ts.pt --output model/shv54_val001.onnx \
    --num-classes 3 --conf-thres 0.001 --iou-thres 0.6 --max-dets-per-class 300

# 2) atc(必须 deactivate venv,用系统 python3)
deactivate
source /usr/local/Ascend/ascend-toolkit/set_env.sh
atc --model=model/shv54_val001.onnx --framework=5 --output=model/shv54_val001 \
    --soc_version=Ascend310P3 --input_format=NCHW --input_shape="image:1,3,544,960" --log=info

# 3) 全量推理(4991 张)
source .venv/bin/activate
export PYTHONPATH=$PWD/AscendDemo/build
python AscendDemo/scripts/run_batch_infer.py --om model/shv54_val001.om \
    --images-root test_assets --out eval/pred_full_val001.jsonl --conf 0.001

# 4) YOLOv5 口径评测 → 6 个产物
python AscendDemo/scripts/eval_yolov5_style.py --gt-root test_assets \
    --pred eval/pred_full_val001.jsonl --out-dir eval/yolov5_style \
    --out-json eval/yolov5_style/metrics.json

9. 产物清单

文件NVIDIA 侧Atlas 300V 侧
resualt.txtdocs/shv54精度数据/resualt.txtdocs/shv54精度数据_atlas/resualt.txt
PR_curve.pngdocs/shv54精度数据/PR_curve.pngdocs/shv54精度数据_atlas/PR_curve.png
F1_curve.pngdocs/shv54精度数据/F1_curve.pngdocs/shv54精度数据_atlas/F1_curve.png
P_curve.pngdocs/shv54精度数据/P_curve.pngdocs/shv54精度数据_atlas/P_curve.png
R_curve.pngdocs/shv54精度数据/R_curve.pngdocs/shv54精度数据_atlas/R_curve.png
confusion_matrix.pngdocs/shv54精度数据/confusion_matrix.pngdocs/shv54精度数据_atlas/confusion_matrix.png
metrics.json—docs/shv54精度数据_atlas/metrics.json(机器可读)

规格:4 张曲线图 2250×1500(figsize=(9,6) + dpi=250),
混淆矩阵 3000×2250(figsize=(12,9) + dpi=250),
resualt.txt 459 字节 / LF / 无 BOM。

Logo

作为“人工智能6S店”的官方数字引擎,为AI开发者与企业提供一个覆盖软硬件全栈、一站式门户。

更多推荐