2026-04-24 — v9_real_balanced_10hz real dump 诊断
本文档记录 v9_real_balanced_10hz 在真实数据 dump 上的直接 CSV 诊断结果,不依赖训练日志里的 aggregate val_metrics。
相关文件:
- dump 目录:
checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz - 统计脚本:scripts/analyze_csv_dump.py
1. 背景
用户的核心问题不是 “aggregate 指标多少”,而是:
real_ov1 / real_ov2 / real_ov3到底差在哪;- 是类错、角度错,还是对的 track 没被最终输出;
10Hz + real mix到底有没有把模型带坏。
为避免继续靠 oracle_* / F20 / LE_CD 猜,我们直接分析了导出的 __pred.csv / __gt.csv。
2. 统计脚本
新增脚本:
python3 scripts/analyze_csv_dump.py \
--dump-dir checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz
默认行为:
- 不做阈值,直接分析 raw
__pred.csv的全部 track
分析阈值后的最终输出:
python3 scripts/analyze_csv_dump.py \
--dump-dir checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz \
--threshold 0.5 \
--threshold-sweep 0.3 0.4 0.6
脚本会输出两类统计:
2.1 GT-side
对每个 GT source/frame 看:
hit_cls_and_angle含义:至少存在一个同类预测,且最佳角误差<=20°class_right_angle_wrong含义:存在同类预测,但最佳角误差>20°no_same_class_pred_but_other_preds_exist含义:这帧模型有别的 active 预测,但没有任何同类预测no_pred_in_frame含义:这帧一个 active 预测都没有
2.2 Pred-side
对 threshold 后的预测看:
matched_tp含义:能和某个 GT 做同类且<=20°的匹配same_class_angle_wrong_fp含义:有同类 GT,但角度没进20°wrong_class_or_spurious_fp含义:没有任何同类 GT
3. 一个重要事实:dump 里的 pred.csv 不是最终输出
这次 v9_real_balanced_10hz 的 pred.csv 保存的是 每帧 4 条 raw track 输出,不是已经过 activity_prob>=0.5 筛选后的最终预测。
这非常重要,因为它允许我们把问题拆成两层:
- raw 4-track 里有没有可用候选
- 过阈值以后,最终留下来的到底是什么
4. Raw 4-track 结果
命令:
python3 scripts/analyze_csv_dump.py \
--dump-dir checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz
核心结果:
4.1 real_ov1
avg_gt/frame = 1.00avg_pred/frame = 4.00hit_cls_and_angle = 54.2%class_right_angle_wrong = 45.8%no_same_class_pred_but_other_preds_exist = 0.0%
解释:
- raw 4 条里,每个 GT 都能找到同类候选
- 其中一半以上角度也已经进了
20° - 所以单源 real 上,raw 候选并不差
4.2 real_ov2
avg_gt/frame = 1.98avg_pred/frame = 4.00hit_cls_and_angle = 37.4%class_right_angle_wrong = 56.9%no_same_class_pred_but_other_preds_exist = 5.7%
解释:
- raw 4 条里,大多数 GT 还是能找到同类候选
- 但主问题已经是角度本身错
4.3 real_ov3
avg_gt/frame = 2.88avg_pred/frame = 4.00hit_cls_and_angle = 33.9%class_right_angle_wrong = 41.6%no_same_class_pred_but_other_preds_exist = 24.5%
解释:
- 即使给满 4 条 raw 候选,仍有
24.5%的 GT 找不到任何同类预测 - 所以
real_ov3从 raw 层面就已经有明显class/source binding问题
5. activity>=0.5 后的结果
命令:
python3 scripts/analyze_csv_dump.py \
--dump-dir checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz \
--threshold 0.5
5.1 real_ov1
avg_gt/frame = 1.00avg_pred/frame = 1.14hit_cls_and_angle = 22.4%class_right_angle_wrong = 40.2%no_same_class_pred_but_other_preds_exist = 37.3%
解释:
- raw 4-track 时,同类候选是
100%存在的 - 过阈值后,
37.3%的 GT 直接变成 “这帧有别的 active 预测,但没有同类预测” - 这说明
real_ov1的主问题不是 “不会预测”,而是:- 对的 track 没被留住
- 或被别的错 track 抢走
- 也就是 decode / track ranking / calibration 问题
5.2 real_ov2
avg_gt/frame = 1.98avg_pred/frame = 1.93hit_cls_and_angle = 17.9%class_right_angle_wrong = 73.9%no_same_class_pred_but_other_preds_exist = 8.2%
解释:
- 轨数和 GT 基本对齐,不是明显少报
- 主要失败项是 同类有了,但角度错
- 所以
real_ov2主问题不是 threshold,也不是主要类错,而是 角度本身错
5.3 real_ov3
avg_gt/frame = 2.88avg_pred/frame = 1.82247帧里有161帧是pred < gthit_cls_and_angle = 26.3%class_right_angle_wrong = 30.2%no_same_class_pred_but_other_preds_exist = 43.5%
解释:
- 这里同时有三件事:
- active 轨数不够
- 同类 track 经常找不到
- 即使找到了,同类里也有不少角度不对
因此 real_ov3 是:
binding错decode少亮轨angle也错
三件事叠在一起。
6. Threshold sweep:是不是纯阈值问题
命令:
python3 scripts/analyze_csv_dump.py \
--dump-dir checkpoints/v9_10hz_eval_dump/v9_real_balanced_10hz \
--threshold 0.5 \
--threshold-sweep 0.3 0.4 0.6
6.1 real_ov1
从 0.3 -> 0.6:
avg_pred/frame几乎不变:1.14 -> 1.05hit基本只在高阈值0.6时下降no_same_cls一直很高:37.3% -> 43.4%
结论:
- 不是简单阈值问题
- 更像是对的 track 本来就没排到最终输出前面
6.2 real_ov2
从 0.3 -> 0.6:
avg_pred/frame几乎不变:1.99 -> 1.91hit几乎不变:17.9% -> 17.8%class_right_angle_wrong一直卡在73%左右
结论:
- 几乎完全不是 threshold 问题
- 就是 角度头本身错
6.3 real_ov3
从 0.5 -> 0.3:
avg_pred/frame从1.82 -> 2.15under_frames从161 -> 140no_same_cls从43.5% -> 34.7%- 但
hit只从26.3% -> 27.0%
结论:
- 降阈值确实能缓一点 “少亮轨”
- 但收益有限,根问题还在
- 所以
real_ov3不是纯阈值问题
7. 最终结论
7.1 每个 split 的主问题
real_ov1- 主问题:decode / track ranking / calibration
- 证据:raw 4-track 同类候选
100%存在,但阈值后大量 GT 找不到同类 track
real_ov2- 主问题:角度本身错
- 证据:轨数基本对,class 也不是主要问题,但
73.9%变成 “同类有了但角度错”
real_ov3- 主问题:binding 错 + 少亮轨 + 角度错
- 证据:
- raw 层 already
24.5%找不到同类 - threshold 后
avg_pred/frame = 1.82 < 2.88 - 同时还有
30.2%的同类角度错
- raw 层 already
7.2 这次问题不是一句 “real 很差” 能说清的
更准确的说法应该是:
real_ov1:内部候选还可以,但最终输出选坏了real_ov2:主要是 spatial regression 错real_ov3:multi-source 下 source binding 和 spatial 一起掉了
7.3 这也解释了为什么只看 aggregate 指标会误判
同一个 LE_CD / F20 很差,背后可能是三种完全不同的失败机制:
- 对的候选存在,但没被输出
- 同类 track 有了,但角度偏得很远
- raw 4-track 里就没把 source 绑定出来
所以以后继续看 real dump 时,应该固定用 scripts/analyze_csv_dump.py,先把问题拆成这三类,再决定改哪一层。