十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

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

YOLOv7自定义数据集训练全指南:格式转换、参数调优与部署

YOLOv7自定义数据集训练全指南:格式转换、参数调优与部署 简介这是一份基于YOLOv7训练自定义数据集的完整课程设计项目面向计算机视觉方向的学生尤其适合完成课程设计、期末大作业或快速入门目标检测实战。项目已获导师指导并取得九十七分高分工程结构完整下载解压后可直接运行无需额外修改。包内共有一百三十一个文件包括三十一个Python训练与推理脚本、二十七个YAML配置文件、十四个XML标注文件、十四个TXT标签列表以及shell脚本、Dockerfile等另有Jupyter notebook入门示例。这些文件覆盖了从数据集准备、标注格式转换、模型配置到训练验证与推理部署的完整流程资源压缩包约一点八五MB轻量易用目前已四百四十一人学习下载。通过该项目读者既能获得一套可复现的目标检测训练框架也能参考其数据组织、参数调整与工程目录设计方式并根据自身任务灵活替换数据集迁移到其他检测场景中。1. 拿到“基于yolov7训练自己数据集完整源码数据”先别急着运行 train.py很多课程设计包一到手就会解压然后立刻执行 train.py期望某个 epoch 后看到自己的检测框。结果往往是先把显存打满再报 KeyError最后在 data.yaml 的 class 数量和 txt 标签不一致上耗掉一下午。YOLOv7 这类仓库本质是一个“训练框架加示例配置”它不能替你理解课程设计里的数据长什么样。正确顺序应该是先确认数据集是 VOC、COCO 还是原生 YOLO txt 格式再检查预训练权重是否存在最后才是调 batch size 和 epochs。这套思路对 YOLOv5、YOLOv8 同样成立。下面按“源码结构 - 数据整理 - 训练参数 - 部署验证”的顺序把一套可复现的操作流程完整串起来。2. 摸清 YOLOv7 源码结构和数据集格式2.1 源码目录里必须出现的几个文件我一般会先对课程设计压缩包做一次“体检”。解压后至少要看train.py、detect.py、models/yolov7.yaml、data/或者config/目录是否存在。YOLOv7 官方仓库和大部分课程设计改造版都沿用了下面的结构yolov7/ ├── train.py # 训练入口 ├── detect.py # 推理入口 ├── export.py # 导出 ONNX/TensorRT 等格式 ├── data/ # 数据集配置 yaml ├── models/ # 网络结构 yaml 与模块定义 ├── utils/ # loss、metrics、datasets 等工具 ├── weights/ # 预训练权重通常是 yolov7.pt └── runs/ # 训练输出包括权重和可视化日志如果runs目录不存在没关系训练时会自动创建。如果weights目录里没有yolov7.pt则要去官方 Release 下载对应的预训练权重或者课程设计包里自带的权重。这里有一个容易踩的坑某些课程设计作者会把已经训练好的 final.pt 放到runs/train/exp/weights/下但train.py默认读取的仍是yolov7.pt。你要想“接着别人的权重继续训练”就必须手动指定--weights runs/train/exp/weights/best.pt否则相当于从 COCO 预训练重新开始。2.2 标签 txt 和 class 列表怎么对应YOLOv7 训练时要求的标注格式是每个图片对应一个同名.txt文件内容为class_id x_center y_center width height坐标均为归一化到 0~1 的浮点数不是像素值。class_id从 0 开始。例如一张 640x640 图片中一只猫的包围框左上角在 (160, 200)右下角在 (480, 440)那么对应的 txt 内容为0 0.500 0.500 0.500 0.375计算过程是x_center (160480)/2/640 0.5y_center (200440)/2/640 0.5width (480-160)/640 0.5height (440-200)/640 0.375。课程设计包里如果自带 label 目录我会随机抽取几个 txt 文件手动计算一遍坐标和图片上的实际目标边框比对。比对时可以直接用 matplotlib 或 LabelImg 打开确认。很多同学训练不收敛是因为标签里混入了负数坐标或者宽高为零这些值不会直接报错只会让 loss 曲线异常。2.3 data.yaml 和 hyp 参数要先看后改源码包里data/目录下通常有coco.yaml正式训练前需要新建一个自己的 yaml内容类似train: data/custom/train.txt val: data/custom/val.txt nc: 2 names: [cat, dog]train和val这里写的是文本文件路径文本里每行是一个图片的绝对路径。不过 YOLOv7 也支持直接写图片目录例如train: data/custom/images/train。nc必须和names长度一致。有的源码包会在每轮训练开始时读取data.yaml检测到nc2但标注文件里出现class_id2就会在计算 loss 时报 index out of range。要避免这个问题可以在训练前写一个小脚本扫描所有 label 文件检查最大 class id 是否小于ncimport os label_root path/to/labels/train max_id -1 for fname in os.listdir(label_root): if not fname.endswith(.txt): continue with open(os.path.join(label_root, fname)) as f: for line in f: cls int(line.split()[0]) if cls max_id: max_id cls print(max class id:, max_id)这段脚本的作用是提前暴露数据标签错误而不是等训练到一半才打印 Warning。另外hyp.scratch.yaml里的lr0、mosaic、mixup等参数对训练效果影响很大。课程设计通常数据量不大我一般会把mosaic: 1.0改成0.5原因是小数据上 mosaic 增强容易让目标变得太小导致早期训练不稳定。后面可以再根据 loss 曲线调回 1.0。3. 把课程设计里的数据集整理成 YOLOv7 能用的格式3.1 判断原始数据是 VOC、COCO 还是 YOLO 格式课程设计数据集的原始格式五花八门最常见的是 VOC 格式JPEGImages/存放图片Annotations/存放与图片同名的 XML 文件。其次是 COCO 的 annotation JSON还有一个用于城市场景的 POI 数据集以及土木方向常见的桥墩病害数据集。这些数据集通常不会直接给 YOLOv7 需要的 label txt所以第一步是统一格式。一个简单的判断方法如果看到.xml就是 VOC如果看到train.json和instances_train.json多半是 COCO 结构如果看到每张图对应的.txt并且文件内容每行五个数字那已经是 YOLO 格式可以直接使用。COCO2017 数据集结构本身是images/train2017和annotations/instances_train2017.json如果课程设计包直接用了这种结构则需要做一次转换。3.2 VOC XML 转 YOLO txt 的推荐脚本下面是常用做法我一般会写一个独立的voc2yolo.py不污染训练源码。它遍历 XML 目录把每个框的坐标转换为归一化格式import xml.etree.ElementTree as ET import os class_names [cat, dog] # 必须和 data.yaml 的 names 一致 def convert_annotation(xml_file, out_file): tree ET.parse(xml_file) root tree.getroot() size root.find(size) w int(size.find(width).text) h int(size.find(height).text) lines [] for obj in root.iter(object): name obj.find(name).text if name not in class_names: continue cls_id class_names.index(name) box obj.find(bndbox) xmin float(box.find(xmin).text) ymin float(box.find(ymin).text) xmax float(box.find(xmax).text) ymax float(box.find(ymax).text) x_center (xmin xmax) / 2.0 / w y_center (ymin ymax) / 2.0 / h bw (xmax - xmin) / w bh (ymax - ymin) / h lines.append(f{cls_id} {x_center:.6f} {y_center:.6f} {bw:.6f} {bh:.6f}) with open(out_file, w) as f: f.write(\n.join(lines))这段脚本的关键在于坐标归一化。宽度高度除以图片宽高而不是除以 640因为模型里会在加载时统一 resize归一化坐标可以避免因为原始分辨率不同导致的问题。脚本里还过滤了不在class_names中的目标物体比如背景标注或 “hard example” 类这样能避免类目编号错位。3.3 COCO JSON 转 YOLO 结构COCO 格式转换需要读取 JSON 中的images和annotations两个数组。annotations里的bbox字段是[x, y, width, height]也就是左上角坐标和宽高和 YOLO 需要的中心点坐标不同。转换脚本如下import json import os def coco_to_yolo(json_path, img_dir, out_label_dir): with open(json_path) as f: data json.load(f) cat_id_to_index {cat[id]: i for i, cat in enumerate(data[categories])} img_id_to_name {img[id]: img[file_name] for img in data[images]} for img in data[images]: img_id img[id] name img[file_name] width img[width] height img[height] label_path os.path.join(out_label_dir, name.replace(.jpg, .txt)) with open(label_path, w) as out_f: for ann in data[annotations]: if ann[image_id] ! img_id: continue x, y, w, h ann[bbox] x_center (x w / 2) / width y_center (y h / 2) / height w_norm w / width h_norm h / height category_idx cat_id_to_index[ann[category_id]] out_f.write(f{category_idx} {x_center:.6f} {y_center:.6f} {w_norm:.6f} {h_norm:.6f}\n)使用时要确认 JSON 中的类别 id 是否连续。COCO2017 的category_id会有间隔比如 1 代表 person2 代表 bicycle但没有 id0 的类别。如果直接使用原始 id就会出现标签里的 class id 大于 nc。上面代码用cat_id_to_index做了映射把原始 COCO 类别压缩成 0 开始的连续编号这是很多课程设计作者会漏掉的一步。3.4 分割 train/val 并校验图片与标签数据准备好后我习惯把全部图片按 9:1 或 8:2 分成训练集和验证集。最简单的方式是把图片路径写入两个 txt 文件供 YOLOv7 的data_ssss对话框读取。但更稳妥的做法是直接按目录划分mkdir -p images/train images/val labels/train labels/val mv $(ls images | head -n 900) images/train/批量移动后要检查是否有图片缺少对应 label。常见问题是课程设计数据里只标注了部分图片导致训练集出现空标签。YOLOv7 在读取数据时对无标签图片会报 “No labels found in image”。我的处理方式是写个脚本自动过滤这些图片import os img_dir images/train label_dir labels/train valid_imgs [] for img_name in os.listdir(img_dir): stem os.path.splitext(img_name)[0] label_path os.path.join(label_dir, stem .txt) if os.path.exists(label_path) and os.path.getsize(label_path) 0: valid_imgs.append(img_name) else: print(skip, img_name) with open(train.txt, w) as f: for img_name in valid_imgs: f.write(os.path.join(os.path.abspath(img_dir), img_name) \n)这段代码做了两件事过滤掉没有标签或标签为空的图片同时生成 YOLOv7 需要的train.txt路径列表。注意os.path.getsize(label_path) 0这个条件因为有些课程设计数据里会存在 0 字节的 txt 文件看起来像有标注实际上没有。4. 调整 YOLOv7 训练参数并执行训练4.1 一个可以直接跑通的基础训练命令数据格式确认无误后训练命令不要堆太多参数先跑一个小配置验证流程能走通python train.py \ --weights weights/yolov7.pt \ --data data/custom.yaml \ --img 640 \ --batch 8 \ --epochs 50 \ --workers 4 \ --device 0这条命令的含义是从 COCO 预训练权重初始化使用data/custom.yaml里的配置将输入图片缩放到 640x640batch size 为 8训练 50 轮使用 4 个数据加载子进程训练设备为第一张显卡。第一次跑的时候建议把--workers调成 0如果出现 dataloader 卡死多半是 Windows 下多进程启动的问题。4.2 关键参数设置表不同参数的取值直接影响训练速度和收敛效果。下面是我基于多次训练课程设计数据集的经验值可以作为起步参考参数推荐值说明img640课程设计常用大小显存不够可降到 416batch8 ~ 16取决于 GPU 显存6G 显存推荐 8epochs50 ~ 100小数据集 50 轮足够验证集 loss 不降就早停lr00.01初始学习率使用预训练权重时不用改workers0 ~ 4Windows 下建议 0Linux 可以 4 或更高hyphyp.scratch.yaml数据量小于 1000 张时建议关闭 mosaic 或调低这里提一个注意点YOLOv7 的--img参数在训练时会同时影响随机裁剪的尺寸范围。--img 640并不代表所有图片都被硬 resize 到 640而是会在 320 到 640 之间随机缩放。如果你希望尽量保留小目标可以加上--rect参数让同一 batch 内的图片使用相近的宽高比减少无意义填充。4.3 小数据集和高分辨率图像的处理技巧课程设计的数据量通常不大可能只有几百张图片如果直接使用完整的 YOLOv7 结构容易过拟合。我常用的做法是换用参数更少的yolov7-tiny.yaml或者保持原始结构但降低输入分辨率。以 6GB 显存为例用--img 640和--batch 8勉强能跑但如果数据里有大量 4000x3000 的桥墩病害图片就必须在训练前统一缩到合理尺寸否则数据加载会成为瓶颈。训练时观察 loss 曲线有个重要习惯:不要只看前几个 epoch。有人看到第 10 轮 loss 还没降到 0.05 就开始调参实际上 YOLOv7 的 loss 是多个头的加权和在前 20 轮会有一个快速下降到平稳的过程。课程设计只要保证验证集 mAP 在上升就说明没有跑偏。我一般在训练到一半时手动检查一次runs/train/exp/下的val_batch0_labels.jpg如果发现标签框和图片中的目标明显错位马上停下来检查数据不要浪费剩余时间。4.4 如何从断点继续或换用新的数据集如果课程设计需要做对比实验比如“自己的数据”和“公开数据集”各训练一次最好在命令行里指定不同的--name参数否则 YOLOv7 会把结果全部写进exp目录。常见做法是python train.py --data data/custom.yaml --name custom_v1 --weights weights/yolov7.pt python train.py --data data/coco.yaml --name coco_baseline --weights weights/yolov7.pt这样runs/train/custom_v1和runs/train/coco_baseline互不干扰。从断点恢复训练时加上--resume runs/train/custom_v1/weights/last.pt注意不是--weights否则会重新初始化优化器。5. 训练结果验证、部署与答辩展示技巧5.1 用 detect.py 快速验证图片和视频训练完成后第一件事不是急着写报告而是用生成的best.pt跑几张之前没见过的图片python detect.py \ --weights runs/train/custom_v1/weights/best.pt \ --source data/custom/images/val \ --conf-thres 0.5 \ --iou-thres 0.45 \ --img 640 \ --save-txt \ --save-conf--save-txt会把检测结果保存成 txt 文件输出行格式和训练标签相同但最后会多一个置信度分数。--save-conf则是把置信度写进 txt方便后续写课程设计报告时统计准确率。--source参数也支持视频文件或摄像头设备号例如 Android 手机 RTSP 流可以写成--source rtsp://192.168.1.10:8554/cam这类地址。这样可以直接在课程答辩现场演示实时检测效果比单纯放几张测试图片更有说服力。5.2 把 YOLOv7 部署到 CPU 或移动端的思路课程设计如果要求“部署”而不只是训练最常见方案是导出 ONNX 或 OpenVINO 格式。导出 ONNX 只需要一行命令python export.py --weights runs/train/custom_v1/weights/best.pt --img 640 --batch 1导出完成后会生成best.onnx。用 ONNX Runtime 在 CPU 上推理时需要处理输入维度[1, 3, 640, 640]和输出层。YOLOv7 输出有三个分支每个分支形状为[1, 255, 80, 80]等这也对应了 COCO 80 类如果你的nc不是 80记得在导出的模型结构里检查输出通道数是否为(5 nc) * 3。这个公式是从 YOLOv7 的 anchor 和回归头来的:每个网格点有 3 个 anchor每个 anchor 的回归量是 5再加上类别数。如果这个数值对不上说明你用了官方的 ONNX 文件而没有重新导出。5.3 把 mAP 和 PR 曲线写进课程设计报告最后一个小技巧是善用 YOLOv7 自带的验证命令来采集指标。不要只从终端复制最后一行 mAP运行下面的命令可以生成整个验证集上的 PR 曲线和混淆矩阵python test.py \ --weights runs/train/custom_v1/weights/best.pt \ --data data/custom.yaml \ --task val \ --conf-thres 0.001 \ --iou-thres 0.6注意--conf-thres设为 0.001目的是在计算 mAP 时把低置信度的检测框也纳入这样才能画出完整的 PR 曲线。输出会在runs/test/custom_v1下生成PR_curve.png、F1_curve.png和confusion_matrix.png。我在答辩前会把 PR 曲线和训练时的 loss 曲线放到同一页 PPT 里然后明确说明“训练 loss 下降不代表模型泛化要看验证集 mAP”这句话对老师来说比贴一堆参数表更显专业。如果数据集中有很多负样本比如背景图片没有目标建议再检查一次混淆矩阵确认没有把所有背景都预测成某一类否则可能是类别权重不平衡或误标导致。本文还有配套的精品资源点击获取
返回列表