ARTICLE DETAIL

资讯详情

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

YOLOV5 6.1全中文注释包实战:从源码解析到训练推理与部署

YOLOV5 6.1全中文注释包实战:从源码解析到训练推理与部署 简介这份资源是YOLOV5 6.1版本的全中文注释代码压缩包面向正在做目标检测项目、准备研究生课题或创新创业大赛的学生与开发者主要解决官方源码注释稀少、阅读门槛高的问题。包内共约2000个文件以py源码、pyc字节码、h头文件、pyi类型声明及pyd动态库为主另含yaml配置、txt说明、mat数据、csv与png样例等压缩包约296.99MB覆盖模型定义、数据加载、训练推理与工具脚本等模块。目前已有2785人学习下载说明其在目标检测入门与二次开发中具备一定参考价值。读者可借助逐行中文注释快速理解YOLOv5 6.1的网络结构、损失计算与推理流程配合配套教程栏目定位关键代码减少自行啃源码的时间适合需要在此基础上改网络、换数据集或撰写论文实验的读者使用。1. YOLOV5 6.1 全中文注释包拿到压缩包之后的第一件事你从某个渠道拿到一个名为「YOLOV5 6.1版本全中文注释压缩包」的文件解压后看到一堆.py文件每个文件里密密麻麻的中文注释——这可能是你第一次真正有机会把 YOLOV5 的源码从头到尾读一遍。但问题来了注释是中文的代码结构却依然是那个经典的models/、utils/、data/三层架构从train.py到detect.py再到yolo.py调用链横跨十几个文件。如果只是打开common.py看到「这是 C3 模块」的注释你依然不知道它在整个前向传播里扮演什么角色。这个压缩包真正值钱的地方不是注释本身而是它给了你一个「可以逐行追问」的入口。配套教程如果只是告诉你「运行train.py就能训练」那和官方 README 没区别。你需要的是注释告诉你这行代码在做什么教程告诉你为什么要这样做而你自己要搞清楚改了会怎样。这篇文章就是按这个逻辑写的——先把这个包的结构和版本特性拆开再讲怎么用它跑通训练和推理最后把注释里不会写的那些坑一个个填上。适合已经跑过 YOLOV5 推理、但读源码时卡在某个模块不知道从哪下手的人也适合想基于 6.1 版本做二次开发但被版本差异搞晕的人。2. 拆开压缩包6.1 版本的目录结构与注释覆盖范围2.1 先确认版本6.1 和 5.0 的差异决定了你读注释的方式YOLOV5 6.1 不是一个简单的补丁版本。从 5.0 到 6.1最明显的变化是models/下多了yolov5n.yaml和yolov5s6.yaml这类配置文件common.py里新增了Focus模块的替代实现detect.py的输出格式也有调整。如果你拿到的中文注释包是基于 5.0 写的直接套在 6.1 上会出现「注释说的变量名在代码里找不到」的情况。常见做法是解压后先看根目录有没有README.md或requirements.txt里面通常会写版本号。如果没有直接看models/yolo.py里Detect类的forward方法——6.1 版本在这里有self.grid的初始化逻辑5.0 没有。另一个快速判断点打开utils/general.py搜索def non_max_suppression6.1 版本在这个函数里增加了max_det参数的默认值处理5.0 的写法不同。确认版本之后再去看注释的粒度。一个合格的全中文注释包应该在以下四个位置有实质性注释models/common.py每个模块的输入输出张量形状、卷积核数量、步长models/yolo.pyDetect头的锚框分配逻辑、损失计算入口utils/loss.pyComputeLoss里正负样本匹配的每一步train.py超参数解析、数据加载、优化器构建的完整流程如果注释只停留在「定义了一个卷积层」这种程度那这个包的价值就大打折扣。你可以在common.py里随便找一个C3模块看注释有没有写清楚cv1、cv2、cv3各自的通道数变化以及bottleneck的堆叠次数。这是判断注释质量的试金石。2.2 目录结构速查每个文件夹对应训练流程的哪一步拿到压缩包后不要急着跑代码先花十分钟把目录结构过一遍。下面这张表是我按实际训练流程整理的你可以对照自己的包检查是否完整目录/文件作用读注释时的关注点data/数据集配置与加载hyp.scratch.yaml里的超参数含义datasets.py里LoadImages和LoadStreams的区别models/网络结构定义yolov5s.yaml的depth_multiple和width_multiple如何影响实际通道数utils/工具函数metrics.py里 mAP 的计算方式torch_utils.py里模型 EMA 的更新逻辑weights/预训练权重存放通常为空需要自己下载或从yolov5s.pt开始runs/训练输出每次训练的results.csv、weights/last.pt、weights/best.pttrain.py训练入口parse_opt()里每个参数的实际作用尤其是--cfg和--weights的配合detect.py推理入口--source支持的文件类型--conf-thres和--iou-thres的默认值export.py模型导出导出 ONNX 时的--opset版本选择动态轴设置这张表不是让你背而是让你在遇到问题时知道该翻哪个文件。比如训练时 loss 不下降第一反应应该是去看utils/loss.py的注释而不是盲目调学习率。再比如推理时框的位置偏移应该去utils/general.py里找scale_coords函数的注释看坐标还原的逻辑有没有被改过。2.3 注释包里的「配套教程」应该怎么用配套教程通常是一个 PDF 或 Markdown 文件内容从环境配置讲到训练推理。但根据我的经验这类教程有一个通病它假设你的环境是干净的而你的机器上可能已经装了三个版本的 PyTorch。所以教程的正确用法不是从头到尾跟着做而是把它当成「命令速查表」。具体来说教程里关于conda create -n yolov5 python3.8的部分你只需要确认 Python 版本是否和requirements.txt里的torch1.7.0兼容。教程里关于pip install -r requirements.txt的部分你需要注意它有没有指定torch和torchvision的版本——如果没有大概率会装到最新版而 YOLOV5 6.1 在最新版 PyTorch 上可能会遇到torch.load的weights_only参数问题。我一般会这样做先按教程走一遍但每执行一条命令就记录下实际安装的版本号。等跑通之后把这些版本号写进一个env_notes.txt下次换机器直接照抄。这比教程本身更有价值因为教程不会告诉你「2024 年 3 月之后 PyTorch 2.6 默认开启了weights_onlyTrue导致加载旧权重报错」这种时效性极强的坑。3. 用注释包跑通训练从数据集配置到超参数调整3.1 数据集准备YOLO 格式的目录结构和 label 文件写法YOLOV5 只认一种数据集格式每张图片对应一个同名的.txt标签文件每行格式为class_id x_center y_center width height所有坐标都是归一化到 0-1 之间的浮点数。这个格式在data/datasets.py的LoadImagesAndLabels类里有详细注释你可以直接看img2label_paths函数它定义了图片路径到标签路径的映射规则。假设你的数据集叫mydata标准目录结构应该是mydata/ ├── images/ │ ├── train/ │ │ ├── 001.jpg │ │ └── 002.jpg │ └── val/ │ ├── 003.jpg │ └── 004.jpg └── labels/ ├── train/ │ ├── 001.txt │ └── 002.txt └── val/ ├── 003.txt └── 004.txt然后新建一个mydata.yaml放在data/目录下# data/mydata.yaml path: ../mydata # 数据集根目录相对于 train.py 的位置 train: images/train # 训练集图片路径 val: images/val # 验证集图片路径 nc: 3 # 类别数必须和 label 文件里的 class_id 最大值一致 names: [person, car, dog] # 类别名称顺序对应 class_id这里有一个注释里经常不写的坑path字段的基准路径是train.py所在目录而不是mydata.yaml所在目录。如果你把mydata.yaml放在data/下path写../mydata是对的但如果写mydata程序会去data/mydata找找不到就报FileNotFoundError。标签文件的生成如果你手头是 VOC 格式的 XML可以用utils/general.py里的xyxy2xywhn函数做转换。但更常见的做法是写一个独立脚本因为 VOC 的bndbox是绝对坐标需要先除以图片宽高再归一化。这个转换脚本在配套教程里通常有但注释包里的版本可能没有处理「图片和 XML 不在同一目录」的情况需要自己补一个os.path.join。3.2 修改配置文件yolov5s.yaml 里哪些参数必须改YOLOV5 6.1 的模型配置文件在models/下最常用的是yolov5s.yaml。打开后你会看到depth_multiple和width_multiple两个参数它们控制模型的深度和宽度缩放。对于自定义数据集这两个值通常不需要改除非你的类别数特别多比如超过 100 类或者图片分辨率特别大。真正必须改的是nc参数。在yolov5s.yaml的head部分每个检测层的args里有一个nc但更规范的做法是只改顶部的nc让程序自动覆盖。6.1 版本的models/yolo.py里parse_model函数会读取yaml[nc]并替换所有检测头的输出通道数。如果你手动改了每个检测层的nc但忘了改顶部的会出现「模型输出通道数和数据集类别数不匹配」的报错。另一个需要关注的是anchors。YOLOV5 6.1 默认的锚框是基于 COCO 数据集聚类得到的如果你的数据集目标尺寸分布和 COCO 差异很大比如全是小目标或全是细长目标建议用utils/autoanchor.py里的kmean_anchors函数重新聚类。这个函数在训练启动时会自动运行但前提是你把--noautoanchor参数去掉默认是开启的。注释包里如果对autoanchor有说明重点看它计算best possible recall的逻辑——如果 BPR 低于 0.98程序会自动重新计算锚框。3.3 启动训练命令行参数逐项拆解训练命令看起来简单但每个参数背后都有对应的代码逻辑。下面这条命令是我在单卡 8G 显存上跑yolov5s的常用配置python train.py \ --data data/mydata.yaml \ --cfg models/yolov5s.yaml \ --weights weights/yolov5s.pt \ --batch-size 16 \ --epochs 100 \ --img-size 640 \ --device 0 \ --workers 4 \ --project runs/train \ --name mydata_exp1 \ --exist-ok逐项说明--data指向你刚才建的mydata.yaml程序会读取nc和names。--cfg指定模型结构。如果你要用yolov5m就改成models/yolov5m.yaml同时--weights也要换成对应的预训练权重。--weights预训练权重路径。如果写就是从头训练但除非数据集非常大否则不建议。--batch-size显存不够就往下调但不要低于 8否则 BN 层的统计量会不稳定。--img-size输入分辨率。必须是 32 的倍数因为 YOLOV5 的下采样总倍数是 32。--workers数据加载线程数。Windows 下建议设为 0 或 2设大了容易卡死。--exist-ok允许覆盖同名实验目录不加这个参数第二次运行会报错。训练启动后终端会打印每个 epoch 的box_loss、obj_loss、cls_loss和mAP0.5。注释包里如果对utils/loss.py有详细注释你可以对照ComputeLoss.__call__的返回值看这三个 loss 分别对应哪部分计算。box_loss是 CIoU 损失obj_loss是目标置信度损失cls_loss是类别损失。如果obj_loss一直不下降大概率是正负样本匹配出了问题需要去看build_targets函数里tobj的赋值逻辑。3.4 训练过程中的监控results.csv 里哪些列值得看训练开始后runs/train/mydata_exp1/下会生成results.csv每一行是一个 epoch 的指标。很多人只看最后的mAP0.5但中间有几列更能反映训练是否健康train/box_loss如果持续下降但val/box_loss上升说明过拟合。metrics/precision精确率。如果精确率很高但召回率很低说明模型太保守可以适当降低--conf-thres。metrics/recall召回率。如果召回率高但精确率低说明模型把很多背景当成了目标。x/lr0学习率。YOLOV5 默认使用余弦退火lr0会从初始值逐渐降到lr0 * 0.01左右。注释包里如果对utils/metrics.py的ap_per_class函数有注释重点看它如何计算每个类别的 AP。YOLOV5 6.1 默认使用 101 点插值法和 VOC 的 11 点插值法不同所以你的 mAP 数值可能比论文里低一点这是正常的。4. 推理与部署detect.py 的参数和导出 ONNX 的注意事项4.1 detect.py 的输入输出--source 支持哪些格式detect.py是推理入口--source参数决定了输入类型。根据data/datasets.py里LoadImages和LoadStreams的注释支持以下格式单张图片--source image.jpg图片文件夹--source images/视频文件--source video.mp4摄像头--source 00 是默认摄像头编号RTSP 流--source rtsp://...需要 OpenCV 支持推理结果默认保存在runs/detect/exp/下。如果是图片会生成带框的图片如果是视频会生成一个 MP4 文件。这里有一个注释里常忽略的点--save-txt参数会把检测框的坐标保存成 YOLO 格式的.txt但坐标是相对于原图尺寸的不是归一化的。如果你需要归一化坐标得自己除以图片宽高。另一个关键参数是--augment开启后会对每张图片做 TTA测试时增强包括翻转、缩放等。这能提升 mAP 约 1-2 个点但推理速度会慢 3-4 倍。如果只是做 demo不建议开如果是打比赛刷榜可以开。4.2 导出 ONNXopset 版本和动态轴的设置YOLOV5 6.1 的export.py支持导出 ONNX、TorchScript、CoreML 等多种格式。最常用的是 ONNX因为可以用 ONNX Runtime 或 TensorRT 加速。导出命令python export.py \ --weights runs/train/mydata_exp1/weights/best.pt \ --include onnx \ --img-size 640 640 \ --batch-size 1 \ --opset 12 \ --dynamic参数说明--include onnx指定导出格式。如果要同时导出多种用逗号分隔比如--include onnx,torchscript。--img-size导出时的输入尺寸。如果后面要用 TensorRT建议固定为 640x640。--batch-size静态 batch 大小。如果加了--dynamic这个参数会被忽略。--opsetONNX 算子集版本。YOLOV5 6.1 建议用 12因为Resize算子在 opset 11 之后才支持nearest模式。--dynamic开启动态 batch 和动态尺寸。如果部署时输入尺寸会变必须加这个参数。导出成功后会在best.pt同目录下生成best.onnx。你可以用onnxruntime加载并推理import onnxruntime as ort import numpy as np # 加载 ONNX 模型 session ort.InferenceSession(best.onnx) # 获取输入名称 input_name session.get_inputs()[0].name # 构造输入数据注意格式是 NCHW且需要归一化到 0-1 img np.random.rand(1, 3, 640, 640).astype(np.float32) # 推理 outputs session.run(None, {input_name: img}) # outputs 是一个列表第一个元素是 [1, 25200, 5nc] 的张量 # 25200 是三个检测层的网格数之和80*80 40*40 20*20 8400但 6.1 版本有调整 print(outputs[0].shape)这里有一个容易翻车的地方ONNX 模型的输出是未经过 NMS 的原始预测框你需要自己实现后处理。YOLOV5 的utils/general.py里有non_max_suppression函数但它是 PyTorch 版本的不能直接用在 ONNX 输出上。常见做法是把 NMS 也导出到 ONNX 里或者用 OpenCV 的cv2.dnn.NMSBoxes做后处理。注释包里如果对non_max_suppression有详细注释你可以照着它的逻辑用 NumPy 重写一遍。4.3 部署到边缘设备树莓派 5 上的性能预期树莓派 5 的 CPU 是四核 Cortex-A76主频 2.4GHz比树莓派 4 快不少但依然没有 CUDA 核心。在树莓派 5 上跑 YOLOV5s用 ONNX Runtime 的 CPU 推理640x640 输入大概能到 3-5 FPS。如果换成 YOLOV5n能到 8-10 FPS。这个速度做实时检测比较勉强但做定时抓拍或低速视频分析够用。部署步骤大致是在树莓派上装好onnxruntime注意要装 ARM64 版本把best.onnx拷过去然后用 Python 脚本调用。如果要用摄像头建议用picamera2库而不是 OpenCV 的VideoCapture因为后者在树莓派上延迟较高。注释包里如果对detect.py的LoadStreams有注释你可以参考它的多线程读取逻辑但树莓派上线程数不要超过 2否则 CPU 会抢资源。5. 避坑与排查注释包里不会写的五个血泪教训5.1 现象训练到一半报 CUDA out of memory但 batch-size 已经调到 4 了原因YOLOV5 6.1 在训练时会缓存验证集的图片和标签如果验证集很大这部分缓存会占用额外显存。另外--workers设得太大也会导致每个 worker 都复制一份数据到显存。解决把--workers设为 2 或 0然后在train.py里找到val_loader的构建部分把batch_size改成训练 batch 的一半。如果还不行加--nosave参数只保存最后一个 epoch 的权重减少显存峰值。5.2 现象mAP 一直是 0loss 也不下降原因最常见的是 label 文件的class_id从 1 开始而不是从 0 开始。YOLOV5 要求class_id从 0 开始如果你从 1 开始程序会把所有目标当成背景。另一个可能是mydata.yaml里的nc和实际类别数不一致。解决用sed或 Python 脚本把所有 label 文件的第一个数字减 1。然后检查mydata.yaml的nc是否等于names列表的长度。最后在train.py里加一行print(dataset.nc)确认程序读到的类别数和你预期一致。5.3 现象推理时框的位置整体偏移或者框比目标大一圈原因detect.py里的--img-size和训练时的--img-size不一致。YOLOV5 在推理时会先把图片 resize 到img-size推理完再还原坐标。如果两个尺寸不一致还原时就会偏移。解决推理时的--img-size必须和训练时完全一致。如果你训练时用的是 640推理时也写 640。另外--rect参数在训练和推理时也要保持一致否则 padding 的方式不同坐标还原也会出错。5.4 现象导出 ONNX 后用 ONNX Runtime 推理结果和 PyTorch 不一致原因PyTorch 的nn.Upsample在导出 ONNX 时如果align_corners没设置对会导致上采样结果有细微差异。YOLOV5 6.1 的common.py里Upsample模块默认align_cornersFalse但某些版本的 PyTorch 在导出时会把它改成True。解决在export.py里找到torch.onnx.export调用加上opset_version12和input_names、output_names。如果还有差异把--dynamic去掉用静态尺寸导出。静态导出的 ONNX 在固定输入尺寸下和 PyTorch 结果几乎一致。5.5 现象Windows 下训练时 DataLoader 报BrokenPipeError或卡死原因Windows 的multiprocessing和 Linux 不同--workers大于 0 时每个 worker 会重新导入主模块如果主模块里有if __name__ __main__之外的代码就会重复执行。解决把--workers设为 0用主进程加载数据。虽然速度慢一点但不会卡死。如果一定要用多 worker确保train.py的所有执行代码都在if __name__ __main__里面。YOLOV5 6.1 的train.py已经做了这个处理但如果你自己改了代码可能会破坏这个结构。6. 把注释包变成自己的知识库二次开发与版本迁移的实用技巧注释包最大的价值不是让你读懂 YOLOV5而是让你在改代码时知道改哪里会影响什么。我自己的习惯是在models/common.py的每个模块定义上方用注释写清楚「输入形状 → 输出形状」和「这个模块在yolov5s.yaml里的第几层被调用」。这样下次想替换某个模块时直接搜索注释里的层号就能找到所有关联点。比如你想把C3模块换成C2fYOLOV8 的结构步骤是先在common.py里新增C2f类然后在yolo.py的parse_model函数里注册这个模块名最后在yolov5s.yaml里把C3改成C2f。注释包里如果对parse_model有详细注释你会看到它通过globals()[m]来动态获取模块类所以只要类名注册了就能用。另一个实用技巧是版本迁移。如果你手头有基于 YOLOV5 5.0 的代码想迁移到 6.1重点检查三个文件models/yolo.py的Detect类、utils/loss.py的ComputeLoss类、utils/general.py的non_max_suppression函数。这三个文件在 5.0 到 6.1 之间改动最大。迁移时不要直接覆盖而是用diff对比两个版本把 6.1 的新逻辑合并进去。最后说一个我踩过的坑注释包里的中文注释有时候会误导你因为注释可能是基于旧版本写的而代码已经更新了。我一般会以代码为准注释只作为理解意图的参考。如果注释和代码矛盾先看git log或CHANGELOG.md如果有的话确认哪个是新的。没有版本控制信息时就看函数签名和默认值——6.1 版本的默认值通常更保守比如conf-thres默认从 0.25 调到了 0.25没变但iou-thres从 0.45 调到了 0.45也没变真正变的是max-det从 1000 调到了 300。这些细节注释里不一定写但代码里一目了然。希望帮到你。本文还有配套的精品资源点击获取
返回列表