事情本身不复杂,线索都在日志里。用 Label Studio 1.16 标注检测数据集后导出 COCO,训练脚本按类别名映射,评估时所有框都判成背景,检查 json 发现 category_id 从 1 开始变成了 0 开始。

第一反应是「导出时合并了多个 labeling config,类别顺序被重排」,验证下来不成立。

这类报错背后常见的原因有几处,逐个排除就行。导出配置里的起始 id 与训练侧约定不一致。还有一种是训练代码把 category_id 直接当类别下标用。

少数情况下是空类别被跳过导致 id 不连续。

动手时先列出 json 里的类别与 id 对照

python -c "import json;d=json.load(open('ann.json'));print([(c['id'],c['name']) for c in d['categories']])"

接着核对标注框里出现的 id 集合

python -c "import json;d=json.load(open('ann.json'));print(sorted({a['category_id'] for a in d['annotations']}))"

然后在数据加载处按名称建立映射并校验连续性

python -c "print({n:i+1 for i,n in enumerate(sorted(names))})"

末了重新导出一份并跑一次小样本过拟合验证

python train.py --data ann.json --overfit 20 --epochs 30

怎么算真的好了,看的是同一批现象。小样本过拟合的 mAP 接近 0.95,类别 id 与名称映射连续,评估里不再出现全判背景。

容易忽略的是,类别 id 是数据契约的一部分,导出工具换版本时最容易变,训练侧按名称映射比按 id 硬编码稳。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。

作者 9823189