ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

yolov5训练数据增加但模型效果下降的原因分析:从数据标注到TaoToken推理链路的排查

yolov5训练数据增加但模型效果下降的原因分析:从数据标注到TaoToken推理链路的排查 1. 数据变多反而掉点yolov5训练数据增加但模型效果下降的典型现场你手里大概率是这样一个局面原来 3 万张图跑 yolov5smAP0.5 能到 0.78后来辛辛苦苦标到 5 万张满心期待冲 0.82结果训练完一看mAP 掉到 0.74PR 曲线整体往右下塌。更气人的是 loss 曲线看着还挺正常训练集 loss 一路降验证集 loss 却在某个 epoch 之后开始抬头。这就是「yolov5训练数据增加但模型效果下降」最典型的现场也是很多人做数据扩充时最容易踩的坑。先把结论摆前面数据量增加本身几乎不会让模型变差让模型变差的是「新增数据带来的分布偏移、标注噪声、类别比例变化以及训练策略没有跟着数据规模一起改」。换句话说问题不在「多」而在「多出来的那部分和原来的不是一回事」或者「优化器还按老节奏走」。这篇文章面向的是已经跑通 yolov5 训练、正在做数据迭代的工程同学也适合刚接手一个「越训越差」项目、需要快速定位原因的算法同学。我会按四条主线拆标注噪声与一致性、类别失衡、过拟合与正则、学习率与训练调度每一块都给可复制的配置和可执行的检查命令。最后用 TaoToken 的统一 Key 调 API 做推理结果对比把「新增数据到底有没有带来收益」这件事量化出来而不是靠感觉。需要提前说清楚一个判断标准不要只看最终 mAP 一个数。你要同时看三个东西——验证集 mAP 曲线、各类别 AP 明细、以及新旧数据分别的推理表现。只看总分你永远不知道是哪个类别被新数据拖下水了。我试过最有效的一招是「分阶段回放」先用原始 3 万张复现 baseline确认能到 0.78再加 5 千张新数据看 mAP 变化再加 5 千张再看。这样你能精确定位是哪一批数据开始让指标掉头。下面所有排查都建立在这个回放框架上。2. 标注噪声与分布偏移yolov5 data.yaml 配置与标注一致性排查新增数据最常见的问题就是标注标准不一致。原来的数据框贴得紧新标注同学习惯留 2 像素边距原来「person」只标可见身体新数据把遮挡的也标了。这种差异人眼扫一遍看不出来但模型会学到一个模糊的边界定义置信度整体下降。先做可视化抽样对比。yolov5 自带val.py可以导出预测框但更直接的是写个小脚本把新旧数据的标注框画出来并排看import cv2, os, random from pathlib import Path def draw_labels(img_path, label_path, color(0, 255, 0)): img cv2.imread(img_path) h, w img.shape[:2] if os.path.exists(label_path): with open(label_path) as f: for line in f: c, x, y, bw, bh map(float, line.split()) x1 int((x - bw / 2) * w); y1 int((y - bh / 2) * h) x2 int((x bw / 2) * w); y2 int((y bh / 2) * h) cv2.rectangle(img, (x1, y1), (x2, y2), color, 2) return img old_imgs random.sample(list(Path(datasets/old/images).glob(*.jpg)), 8) new_imgs random.sample(list(Path(datasets/new/images).glob(*.jpg)), 8) # 分别拼接保存肉眼对比框的松紧、遮挡处理、类别命名重点看三件事框的松紧是否一致、遮挡目标标不标、类别名有没有同义不同名比如 car 和 automobile 混用。类别名不一致是隐形杀手data.yaml 里写 3 类实际标注文件里出现第 4 个 class id训练时不会报错但那一类永远学不好。data.yaml 本身要保证路径和类别严格对应# datasets/merged/data.yaml path: /data/datasets/merged train: images/train val: images/val test: images/test nc: 3 names: 0: person 1: helmet 2: vest改完 data.yaml 后用一行命令统计每个类别的实例数确认没有越界 idfor f in datasets/merged/labels/train/*.txt; do awk {print $1} $f done | sort | uniq -c | sort -rn如果输出里出现nc之外的 id比如你只定义了 0/1/2 却冒出 3那这批数据必须先清洗。分布偏移的检查可以用亮度、尺度直方图对比新增数据如果整体偏暗或目标尺度小一个量级模型的特征统计会被拉偏。处理办法是移除明显离群样本或者对新增数据做与旧数据一致的增强后再入训。注意不要为了凑数量把低质量样本硬塞进去。5 万张里混 3 千张错标比老老实实用 4.7 万张干净数据更伤指标。3. 类别失衡与训练策略hyp 超参与学习率调度可复制配置数据扩充经常把类别比例搞乱。原来 person:helmet:vest 是 6:3:1新增数据来自另一个场景变成 2:2:6少数类被进一步稀释AP 直接崩。先统计新旧分布echo old ; cat datasets/old/labels/train/*.txt | awk {print $1} | sort | uniq -c echo new ; cat datasets/new/labels/train/*.txt | awk {print $1} | sort | uniq -c如果失衡加剧两条路重采样或者在 loss 里加权。yolov5 的hyp.scratch-low.yaml里可以调cls和obj的增益但更稳的是用--weights做增量微调先加载旧模型权重再喂新数据。学习率是最容易被忽略的点。数据量翻倍如果你还用原来的lr00.01和epochs100模型在后期会震荡。线性缩放规则在这里适用batch 不变时数据量增加主要影响的是训练步数建议按比例增加 epochs同时把lr0略微下调配合余弦退火。# hyp.data-v2.yaml lr0: 0.008 # 原 0.01数据量增大后略降 lrf: 0.01 # 最终学习率系数余弦退火到 lr0*lrf momentum: 0.937 weight_decay: 0.0005 warmup_epochs: 3.0 warmup_momentum: 0.8 box: 0.05 cls: 0.5 obj: 1.0训练命令带上增量权重和更长的调度python train.py \ --data datasets/merged/data.yaml \ --weights runs/train/baseline/weights/best.pt \ --hyp hyp.data-v2.yaml \ --epochs 150 \ --batch-size 32 \ --img-size 640 \ --cos-lr \ --name merged_v2过拟合的判断看验证 loss。如果 train loss 持续降、val loss 在 60 epoch 后连续 10 个 epoch 不降反升说明正则不够。加dropoutyolov5 在分类头有dropout参数、提高weight_decay、或者加强 Mosaic/MixUp 增强。反过来如果 train 和 val loss 都高且平是欠拟合得加 epochs 或换更大模型yolov5s 换 yolov5m/l。验证集污染也要查。新增数据如果和 val 有重叠同一段视频抽帧指标会虚高或虚低。用文件哈希去重md5sum datasets/merged/images/train/*.jpg | awk {print $1} | sort train.md5 md5sum datasets/merged/images/val/*.jpg | awk {print $1} | sort val.md5 comm -12 train.md5 val.md5 # 有输出就是泄漏4. 用 TaoToken 统一 Key 做推理对比验证新增数据是否真带来收益训练指标是一回事实际推理表现是另一回事。要判断新增数据有没有用最直接的办法是拿同一批测试图分别用 baseline 和 merged 模型推理对比检测结果。这里用 TaoToken 的统一 Key 调 API 做批量推理对比省去本地环境切换的麻烦。先在控制台创建 Key地址是 https://taotoken.net/api-keys 模型对话入口在 https://taotoken.net/models 长期做编码和 Agent 任务可以看 https://taotoken.net/coding-plan 。API 基址统一用 https://taotoken.net/api 不要加多余路径。调用示例PythonOpenAI 兼容格式import base64, requests, json API_KEY sk-你的TaoTokenKey BASE_URL https://taotoken.net/api/v1/chat/completions def infer(image_path, model_idgpt-4o): with open(image_path, rb) as f: b64 base64.b64encode(f.read()).decode() payload { model: model_id, messages: [{ role: user, content: [ {type: text, text: 列出图中所有目标及其边界框JSON 格式}, {type: image_url, image_url: {url: fdata:image/jpeg;base64,{b64}}} ] }] } r requests.post(BASE_URL, headers{Authorization: fBearer {API_KEY}}, jsonpayload) return r.json() print(json.dumps(infer(test/sample_001.jpg), ensure_asciiFalse, indent2))把 baseline 和 merged 两个模型对同一批图的检测结果都跑一遍统计每个类别的检出数量和框位置差异。如果 merged 模型在新增场景上检出更全、误检没增加说明数据增量有效如果某些类别反而漏检变多回到第 2、3 节查那部分数据的标注和比例。提示推理对比时固定同一批测试图且这批图不能出现在训练集里否则对比没有意义。5. 常见报错与排查对照401、local proxy failed、reading choices、OAuth接入和训练过程中会碰到几类高频报错逐个对照处理。401 UnauthorizedKey 无效或没带上。检查Authorization: Bearer sk-xxx是否完整Key 是否在 https://taotoken.net/api-keys 里被禁用。注意 Base URL 必须是https://taotoken.net/api/v1/...少写/v1或写成别的域名都会 401。local proxy failed本地网络层拦截了请求。检查系统环境变量HTTP_PROXY/HTTPS_PROXY是否指向了不可用的地址清掉再试。这类报错和模型服务本身无关是本地链路问题。reading choices 相关报错如KeyError: choices返回体结构和你预期不符通常是请求被拒或返回了错误对象。先把原始r.text打出来看别直接取choices。常见原因是 model id 写错或图片 base64 过大被截断。OAuth 报错多出现在 Claude Code 或 Codex 类工具接入时。如果用 CC Switch 或 Cline MCP 配置三件套必须写全——Base URL、Key、Model ID缺一个就会走默认 OAuth 流程然后失败。Codex 的auth.json里要显式写{ base_url: https://taotoken.net/api, api_key: sk-你的TaoTokenKey, model: gpt-4o }Claude Code 接入时同理Base URL 用https://taotoken.net/apiKey 填控制台生成的Model ID 按文档填。配置完先跑一个最小请求验证别一上来就批量。训练侧的报错也顺带说两个AssertionError: train and val labels not found多半是 data.yaml 路径写错用绝对路径最稳CUDA out of memory在数据量增大后常见降 batch-size 或开--multi-scale前先确认显存。6. 把排查变成流程从数据入库到推理验证的固定动作与其每次掉点都从头猜不如把上面几步固化成流程。数据入库前跑一遍类别 id 校验和哈希去重训练前对比新旧分布直方图训练中盯 val loss 和各类别 AP训练后用 TaoToken 统一 Key 做推理对比确认新增数据在真实样本上的收益。具体动作清单第一步uniq -c统计类别 id越界就清洗第二步comm -12查验证集泄漏第三步按数据量比例调 epochs 和 lr0用余弦退火第四步增量微调时加载旧权重第五步推理对比固定测试集用 https://taotoken.net/api 统一调用。如果排查完发现是模型容量不够从 yolov5s 换到 yolov5m 或 yolov5l再跑一轮对比。如果确认是新增数据质量问题宁可回退到干净子集也别硬训。数据迭代的核心不是「多」是「一致且有效」。把这套流程跑顺下次再遇到 mAP 反降你半小时内就能定位到是哪一环出了问题。
返回列表