事情本身不复杂,线索都在日志里。用 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 硬编码稳。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
