ARTICLE DETAIL

资讯详情

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

YOLOv11源码实战:从推理结果保存到自定义训练与小目标优化

YOLOv11源码实战:从推理结果保存到自定义训练与小目标优化 简介YOLOv11 是 YOLO 目标检测系列的新一代算法ultralytics 版本在此基础上进一步优化了工程易用性。这份压缩包共含 46 个文件仅 7.34MB体积轻量主要文件类型包括 Python 脚本.py、可执行程序.exe、动态链接库.dll和 Python 扩展模块.pyd并带有 cmd 命令配置、md/txt 说明文档及 license 授权文件。包内明显集成了可运行的 Python 环境与源码级组件配套构建、安装、测试等命令脚本及若干辅助工具脚本可在 Windows 平台上快速部署或二次开发适用于快速验证环境、学习源码结构或离线部署等场景。目前已有 210 人学习对于希望低成本接触 ultralytics 版 YOLOv11 的入门者来说是一个可以快速上手的小型代码环境。 如果你手头刚好有这样一个压缩包大概率是刚接触YOLO或者在网上看到别人分享后顺手存了下来。不管哪种情况解压完看到一整个ultralytics目录时最懵的往往不是代码看不懂而是不知道从哪里开始。实际上这套源码就是目标检测领域这几年最活跃的仓库之一YOLOv11代码里一般写作YOLO11是它当前主推的检测模型一次把目标检测、实例分割、姿态估计、旋转框识别和图像分类全部收进了同一个引擎接口统一得相当彻底。这篇博文不会逐行讲源码而是把“解压之后到部署之前”这一路的完整链路拆开推理结果怎么保存、网络结构在哪个文件里改、自定义数据集怎么训、小目标怎么优化最后再聊聊ultralytics对RT-DETR这类非YOLO模型的支持方式。适合刚入门目标检测的学生、要落地项目的工程师以及想基于源码做模型改进的人。1. 解压之后别急着跑先把源码包变成可调试的环境1.1 为什么我一直推荐用独立环境装这套源码ultralytics对Python版本不算挑剔但torch版本往往比你想的更敏感。直接用系统Python装哪天系统上有另一个项目需要降级torch两边就会互相打架。我自己的习惯是用conda单独建一个环境Python版本固定在3.10。PyTorch 2.0往后对3.8以上的支持都不错3.10是在兼容性和第三方库覆盖面上最稳的没必要去追3.12或3.13。conda create -n yolo11 python3.10 -y conda activate yolo11很多人会在这一步卡住因为conda默认源在国内速度一般。装完环境后顺手换一下国内镜像源几分钟就能省下大把等待时间属于装环境的基本操作。1.2 可编辑安装才是研究源码的正确姿势如果你只是“用”YOLOv11直接pip install ultralytics就够了。但既然你手里拿的是源码包我建议用可编辑安装cd ultralytics pip install -e .-e .的意思是安装当前目录下的项目但不会把代码复制到site-packages而是原地引用。之后你改了ultralytics包里的任何py文件下一次import就会生效不用反复重装。对于想读源码、改结构、二次开发的人来说这一步几乎是必须的。如果只是临时跑一下推理直接pip装也行但代码原目录就变成了“参考文档”改什么都没反应调试成本一下就上来了。torch我习惯显式装不依赖ultralytics自动拉依赖pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121如果你的机器没有GPU把cu121换成CPU版本即可推理一样能跑只是训练会很痛苦。1.3 一行命令验证整条链路是否跑通装完到底成没成跑一次最小推理就清楚了yolo predict modelyolo11n.pt sourcehttps://ultralytics.com/images/bus.jpg第一次运行会自动下载yolo11n.pt权重默认放在当前目录。如果下载特别慢可以去GitHub的Releases页面手动下载权重文件放到项目根目录CLI会优先识别本地文件。跑完之后结果会自动存到runs/detect/predict/下包含原图加检测框的可视化结果。这一步能通过说明torch、ultralytics、权重加载、推理管线、结果保存这条链路已经全通了。验证安装版本也可以用import ultralytics print(ultralytics.__version__)能看到类似0.3.x的版本号就说明包导入正常。1.4 目录结构里最值得先看的几个文件解压后你会看到ultralytics/是主包examples/、tests/、docs/是辅助。我建议先翻这几个文件比从入口一路读下去高效得多ultralytics/cfg/models/11/yolov11.yaml网络结构定义v11的backbone和head全在这里ultralytics/cfg/datasets/coco8.yaml一个迷你数据集配置跑训练demo时直接用这个ultralytics/engine/predictor.py推理主逻辑preprocess、inference、postprocess全在这里ultralytics/engine/trainer.py训练主循环loss、optimizer、scheduler都从这里进去。先把这几个文件各翻一遍你对整个项目的骨架就有概念了。2. 用几种姿势调用推理以及结果的保存与落地2.1 CLI和Python两套入口怎么选ultralytics同时提供了CLI和Python API。CLI适合快速验证和批处理一条命令就能跑完一个文件夹yolo predict modelyolo11n.pt source./images imgsz640 conf0.25 device0source参数很宽容单张图片、文件夹、视频文件、摄像头ID、甚至URL都能直接传。conf是置信度阈值低于这个值的框会被过滤掉。iou控制NMS的容忍度越小越严格。imgsz默认640显存紧张就降到512或480。Python API适合嵌入到项目里后面要接业务逻辑。两种入口底层是同一套代码没有功能差异选哪种纯看场景。2.2 results对象里到底装了什么以Python API为例from ultralytics import YOLO model YOLO(yolo11n.pt) results model.predict(bus.jpg) r results[0] print(r.boxes.xyxy) # [N, 4]左上右下坐标 print(r.boxes.conf) # [N]每个框的置信度 print(r.boxes.cls) # [N]类别索引 print(r.names) # {0: person, 1: bus, ...} print(r.masks) # 分割任务才有 print(r.keypoints) # 姿态任务才有注意predict返回的是一个列表每个元素对应一张输入图即使你只输入了一张图也要先取results[0]。坐标和类别都是tensor如果后续要转列表或者存数据库记得先.cpu().numpy()再处理。2.3 三种保存结果的方式自动保存、手动可视化和结构化导出这是很多人第一次用v11会卡住的地方热词里“yolov11保存推理结果”反复出现确实是个高频需求。第一种最省事predict时加saveTrueresults model.predict(bus.jpg, saveTrue)结果自动存到runs/detect/predict/文件名自动生成不用自己管。第二种是手动可视化适合你想把检测框画到特定位置、或者给结果加后处理from PIL import Image im_bgr r.plot(line_width2) im_rgb Image.fromarray(im_bgr[..., ::-1]) im_rgb.save(output.jpg)plot()返回的是BGR顺序的numpy数组直接用PIL保存会偏蓝。用[..., ::-1]把通道翻回来就行。如果你用cv2.imwrite写就不用翻转OpenCV自己就是BGR顺序。第三种是结构化导出适合对接业务系统把检测结果变成可以入库的数据import json r.save_txt(labels/) # 每行class cx cy w h归一化坐标YOLO格式 r.save_crop(crops/) # 把每个目标抠出来单独存图 data json.loads(r.tojson()) # 完整JSON含坐标、置信度、类别可入数据库三种方式各有用处自动保存省事手动可视化灵活结构化导出负责对接下游。批量推理时建议用streamTrue它会把图片按需加载处理一帧释放一帧不会一次性把所有结果都压在内存里results model.predict(sourcevideos/street.mp4, saveTrue, streamTrue) for res in results: print(len(res.boxes))2.4 一个很容易坑的问题图片颜色不对如果你用plot后用matplotlib显示颜色会偏蓝不是模型错了是通道顺序问题。这类问题刚入门时几乎人人都会遇到记住一点ultralytics内部处理图像用的是BGRplot返回的也是BGR只要显示层用OpenCV就没错用PIL/matplotlib就得手动转RGB。3. 读懂yolov11的yaml从网络结构到参数规模的映射3.1 四个基础规格与scale参数yolov11的yaml文件在ultralytics/cfg/models/11/yolov11.yaml。打开后你会在最顶上看到一段scales配置这就是模型规格的调节器规格depth_multiplewidth_multiplemax_channels典型场景yolo11n0.330.251024边缘设备、实时性优先yolo11s0.330.501024一般服务端推理yolo11m0.670.50768精度与速度均衡yolo11l1.001.00512高精度任务yolo11x1.001.00512精度优先显存充足depth控制每个block堆叠几层width控制通道数的缩放系数max_channels控制通道数上限。以yolo11n为例width是0.25意味着基准64通道会变成16通道这就是为什么n版模型只有两三百万参数。你得理解这个机制后面想自己定义“比n大一点、比s小一点”的规格时直接改scales就行不用一个个层去调。3.2 C3k2、C2PSA和Detect三个关键词看懂v11的设计v11相比v8主干上最核心的变化是C3k2和C2PSA。C3k2是从C3和C2f一路演化来的。它把输入特征在中间分叉一部分走标准卷积和split另一部分直接concat过去减少了中间变量占用的内存同时让梯度回传路径更短。这个名字看起来新本质上是对v8里C2f的又一次“轻量化重排”。C2PSA是v11放进backbone最后一层倒数第二层的模块在C2结构的第二条路径里嵌入了多头自注意力机制。这一步的意图很直接让网络在高层特征上增强全局信息的感知对遮挡、密集目标的表征更友好。注意力模块的参数量和计算开销都不小所以只放在高层不在浅层用。Detect部分依旧是解耦头分类分支和回归分支分开回归分支采用anchor-free和DFL。它输出三个尺度的特征图对应stride 8、16、32分别负责小、中、大目标。这个设计直接决定了后续“加P2分支”这个优化的可行性。3.3 从yaml到“层号”调试网络结构时最实用的技能yaml里每一行都代表一层from字段写的是这一层接收哪些层的输出负号表示相对前面第几层。比如- [-1, 6, C3k2, [512, False, 0.25]]的意思是输入来自上一层输出再接6个C3k2模块通道数512。想验证自己理解的网络结构最直接的办法是from ultralytics import YOLO model YOLO(yolo11n.yaml) model.info()model.info()会打印每一层的输出shape和参数量每一层的实际张量尺寸一目了然。想知道某个模块输出是什么维度就改一版看看比对着论文数结构快多了。3.4 model.yaml、预训练权重和任务头的关系YOLO(yolo11n.yaml)代表从网络结构开始初始化权重全是随机数这是从零训练的前提。YOLO(yolo11n.pt)则是加载已经训练好的权重同时也包含结构信息。想从头训练一个自定义任务时用前者想在COCO预训练基础上微调时用后者。ultralytics会自动根据任务切换输出头detect任务用Detect模块segment任务用Segment模块pose任务用Pose模块。所以同一个yaml文件改一下任务设置就能切换不同的任务头这一点在改造自定义模型时会非常有用。4. 自定义数据集训练一套能直接抄的配置文件与训练参数4.1 数据目录和标签长什么样ultralytics默认使用YOLO格式标注一个txt文件对应一张图片文件名相同、扩展名不同。目录结构如下ROOT/ images/ train/ 0001.jpg 0002.jpg val/ 0001.jpg labels/ train/ 0001.txt 0002.txt val/ 0001.txtlabels里的每行格式是class x_center y_center width height注意三点类别编号从0开始坐标全部归一化到0~1之间images和labels的子目录名必须一致。很多新手把train和val的图片放一个文件夹、标注放另一个文件夹结构对不上就会报 “no labels found”。4.2 data.yaml的坑路径写相对还是绝对data.yaml是训练时的数据集说明文件path: /home/user/datasets/myproject train: images/train val: images/val nc: 3 names: [cat, dog, bird]path是根目录train和val是相对于path的路径。这个字段经常有人写错写成绝对路径反而容易因为换机器报错写成相对path下的路径最稳。你可以在命令行里手动跑一个检查命令确认数据集没问题yolo val datamyproject.yaml modelyolo11n.pt如果数据配置有误这一步会给出比较具体的报错提示。4.3 一条能跑起来的训练命令以yolo11s为例yolo detect train modelyolo11s.pt datamyproject.yaml epochs100 imgsz640 batch16 device0 patience50参数含义拆开讲modelyolo11s.pt加载COCO预训练权重做微调比modelyolo11s.yaml从零训练收敛快得多精度通常也更高。batch按显存来。太大会OOM太小会让梯度噪声变大。Ultralytics支持batch-1让它自动搜索当前显存能容纳的最大batch。epochs小数据集100轮基本够看趋势大项目通常200~300。patience验证集指标连续多少轮不提升就早停50是常用值防止过拟合白烧时间。cacheTrue小数据集时把数据缓存到内存加载速度明显提升。训练产物在runs/detect/train/下weights/best.pt和weights/last.pt的区别要分清best是按验证集指标选出的最优权重last是最后一轮的权重。训练中断后可以用resumeTrue从last.pt继续跑而不是用best。有人用best.pt去resume结果优化器状态对不上效果会打折扣。常用参数速查参数作用我常用的值lr0初始学习率0.01微调用0.005warmup_epochs预热轮数3cos_lr余弦学习率衰减TruemosaicMosaic增强是否开启1.0小目标调0.5fliplr水平翻转概率0.5scale随机缩放范围0.5~1.54.4 第一次训练最容易遇到的三个错第一个错误是找不到标签。报错 “no labels found in ...”不用怀疑就是目录结构或者data.yaml路径对不上按上面的结构检查一遍。第二个是CUDA out of memory。先降batch到4或2再不行就降imgsz到512或480。如果还想再省把cacheFalse开成False减少内存占用。训练是迭代过程先把管线跑通再去追性能和内存。第三个是训练过程中loss突然变NaN。多数情况是标签坐标越界或者某些类别没有训练样本。先用check_det_dataset检查数据集from ultralytics.data.utils import check_det_dataset check_det_dataset(myproject.yaml)它会打印每个类的实例数、目标尺寸分布等信息一眼就能看出哪个类别样本过少或者哪些标注坐标异常。5. 小目标检测优化我在实际项目里踩过的坑和有效手段5.1 为什么v11的小目标效果仍然不够好很多人以为换了新版模型小目标检测就会自动变好实际远没这么简单。三个原因叠加导致小目标依然是老大难一是输入分辨率。默认imgsz是640一个20×20像素的小目标缩放到640尺度后可能只剩3×3个像素特征提取阶段就已经丢掉大部分信息。二是下采样倍数。v11的head在stride 8/16/32上输出特征stride 32的特征图对于小目标来说一个目标的信号可能只落在一个格点上。三是数据分布。实际项目里小目标往往占少数如果标注时框还不准模型基本学不到有效的小目标特征。5.2 最直接有效提高输入分辨率并配合多尺度训练既然信息在缩放时丢了最直观的解法就是把输入放大。训练时用1280yolo detect train modelyolo11s.pt datamyproject.yaml imgsz1280 batch8 device0推理时同样用1280yolo predict modelbest.pt sourcetest/ imgsz1280代价是计算量和显存几乎按分辨率平方上涨速度会明显变慢。显存不够时用batch1硬扛或者开启rectTrue它会让batch内的图片按长宽比分组减少padding造成的无效计算。5.3 数据的功夫在数据里先查目标尺寸分布改网络之前先统计一下数据集里小目标占比按COCO的定义小于32×32像素算小目标。把标注文件读出来用归一化框宽高乘以图片宽高就能算出实际像素尺寸。我做过一个遥感项目当时小目标占比不到5%后来把训练集中小目标样本补到20%以上mAP直接涨了4个点比改网络结构收益大得多。5.4 网络层面给检测头加P2分支数据补完之后效果还不够再考虑动网络。社区里常见的做法是给检测头增加P2分支P2是2倍下采样的特征图分辨率是输入的1/4保留了更多小目标的细节纹理。具体思路是在backbone的第二个C3k2输出后面接一个通道对齐的卷积得到P2特征然后把head里Detect的输入[P3, P4, P5]扩展为[P2, P3, P4, P5]同时调整分类和回归分支的输入通道数。GitHub搜一下yolov11-p2.yaml能找到很多人改好的版本原理就是上面这几步。代价也要讲清楚P2特征图分辨率高计算量和显存会明显上涨训练速度可能下降20%以上而且大目标的精度有时候会略降。所以P2分支适合小目标占比高、且对延迟不敏感的落地场景不是万金油。5.5 推理阶段兜底放宽NMS和置信度模型训练完推理参数也值得调。默认conf是0.25小目标置信度普遍偏低降到0.1能捞回不少真目标代价是假阳性增多。iou从0.45放宽到0.5或0.6能让NMS不那么激进地合并邻近框。max_det300可以防止密集场景下目标被截断。这些参数调完记得在验证集上重新评估别单凭一两张图的视觉感受下结论。5.6 小目标改进效果的验证方法改进有没有效果不能只看总mAP。训练完看results.png里的PR曲线和召回率重点观察小目标子集上的Recall变化。如果recall上去了但precision掉了很多说明模型确实多检出了小目标只是误检也随之增加这时候再去调NMS和置信度才有意义。6. 在ultralytics架构下扩展RT-DETR接入与模型导出的进阶玩法6.1 用同一套接口跑RT-DETRultralytics不只支持YOLO系列还顺手把RT-DETR也整合了进来。RT-DETR是端到端检测模型不需要NMS后处理。热词里反复出现“在ultralytics中训练rtdetr-r18/r34”说明不少人想把RT-DETR也纳入这套统一训练管线。官方预训练权重是RT-DETR-L和RT-DETR-X推理写法from ultralytics import RTDETR model RTDETR(rtdetr-l.pt) results model.predict(bus.jpg, saveTrue)训练自定义数据集时yolo detect train modelrtdetr-l.yaml datamyproject.yaml epochs100 imgsz640数据格式和YOLO完全一致不用额外转换这是ultralytics把所有模型收编进同一套管线的巨大优势。6.2 在ultralytics里改造rtdetr-r18/r34的yamlRT-DETR的backbone是ResNet在ultralytics的cfg/models/rt-detr/目录下rtdetr-l.yaml把ResNet拆成了多个stage每个stage的层数和通道数就是照着ResNet-50来的。想做成r18或r34版本核心就是对照ResNet结构改yaml里backbone各stage的blocks数量ResNet-18为[2, 2, 2, 2]ResNet-34为[3, 4, 6, 3]通道数分别对应[64, 128, 256, 512]。neck部分的encoder和decoder隐藏维度可以相应缩小不然整体计算量还是偏大。改完之后用yolo detect train modelrtdetr-r18.yaml data...验证能不能正常解析。RT-DETR走的是集合匹配的loss显存占用比同规模YOLO高不少训练时把batch先调小跑通之后再慢慢往上试。6.3 模型导出从best.pt到onnx再到engine训练完了要部署ultralytics也给了统一导出入口yolo export modelbest.pt formatonnx imgsz640 yolo export modelbest.pt formatengine device0 halfTrue第一条导出ONNX这是中间格式几乎所有推理框架都能接。第二条导出TensorRT的engine格式需要宿主机有GPU并且安装好了TensorRThalfTrue启用FP16推理速度通常能再快一截。导出时注意imgsz必须和部署端要求的输入尺寸一致导出后再改分辨率又要重新导一次。遇到过ONNX中间节点过多导致推理变慢的情况优先检查导出的简化选项比如opset12这种兼容性设置。6.4 源码阅读的入口如果想二次开发从哪里下手最后一个话题回到“源码”本身。想真正深入改造我建议按这个顺序读先读ultralytics/engine/predictor.py看推理全流程preprocess、inference、postprocess三个方法分开读再读ultralytics/nn/tasks.py里的parse_model它是把yaml转化成模型结构的核心读懂了就知道yaml里的每一行参数怎么映射成代码最后读对应任务的训练脚本比如ultralytics/models/yolo/detect/train.py看loss是怎么组装出来的。我自己这些年用ultralytics最大的体会是千万不要一开始就想着去读整个项目一定要带着一个具体问题去读。比如“小目标检测不好我想加一个P2层”那你就沿着yolov11.yaml找到Detect层的输入再去tasks.py看head怎么构建顺着这条线走两天就能把相关逻辑摸透。抛开具体问题去读很容易在几百个文件里迷路。模型改进这件事动结构之前永远先问自己一句数据干净了吗分辨率提上去了吗如果这两个问题都没想清楚就改网络大概率只是把钱和算力花在了错误的地方。本文还有配套的精品资源点击获取
返回列表