
简介目标检测是计算机视觉的核心任务之一YOLO系列凭借端到端的实时检测能力成为工程实践首选。YOLOv11作为新一代模型在骨干网络与特征融合上进一步优化即使在小规模数据集上也能实现高精度收敛。本文基于一套涵盖薯片、可乐、红牛、养乐多等七类商品的真实场景数据集从YOLOv11格式的标注解析、数据校验、环境配置到模型训练、loss曲线解读与类别不平衡处理再到实时推理与边缘端部署完整呈现零售场景目标检测的落地路径。该方案可应用于自动售卖机商品识别、货架商品检测与便利店结算辅助等场景为开发者提供可复用的工程参考。1. 一千多张罐装饮料图片到底能训练出什么效果先说结论用这套一千多张、七类目标、YOLOv11格式标注的数据集跑出来的模型放在货架识别、自动售卖机商品识别、便利店结算辅助这类场景里是完全能落地的。我拿到这个压缩包的第一反应是看类别——薯片、东鹏特饮、红牛、芬达、养乐多、可乐、雪碧一共七个类别。你仔细看会发现这里面既有罐装饮料也有瓶装饮料还混了一类零食薯片。这种类别组合不是随便拍的它对应的正是超市冷柜、便利店收银台、自动售货机里最常被拿起来又放下的那几样东西。换句话说这个数据集不是为了学术刷榜而是奔着真实场景去的。一千多张图片听起来不多但对于单品类检测任务来说够用了。YOLO系列模型在小数据集上的表现一直可以尤其是yolov11这种新版本backbone和neck的改进让它在样本量不大的情况下也能收敛得不错。关键是标注质量而不是图片数量。如果你的标注文件里框的位置偏了、类别标反了一万张图也是白搭。所以这篇文章我不会只讲怎么跑通训练会把标注文件的结构、格式验证、目录组织、训练参数这些细节一并拆开说清楚。这套数据集适合谁三种人。第一种是想入门YOLOv11目标检测的开发者拿现成标注好的数据跑一遍完整流程比自己从零标数据省太多事第二种是做零售场景识别的工程师虽然最终要标自己的商品但可以用这套数据先把pipeline跑通包括数据加载、训练、推理、导出第三种是给学生和研究者用来做数据增强策略、类别不平衡处理、轻量化部署的实验素材。一句话你缺的不是模型代码是一份干净、格式正确、类别贴近真实场景的训练数据这套东西正好补上这块。2. 拿到zip之后解压、目录结构和标注文件拆解2.1 先解决zip解压的那些破事这个数据集以.zip格式分发按理说双击解压就行但实际下载数据集的过程中踩坑的人不在少数。尤其是从网盘、聊天工具里转存的文件经常遇到几种报错file is not a zip file文件头损坏下载不完整或者被篡改了。invalid zip archive: could not find eocdEOCDEnd of Central Directory记录找不到通常是zip文件的结尾被截断说明上传或下载过程中丢了字节。分卷压缩包如果下载到的是.z01和.zip的组合说明原文件被分卷压缩了.z01需要和主.zip放在同一目录下才能完整解压。我建议养成一个习惯拿到zip先不要急着双击先看文件大小是否和发布页面标注的字节数一致。然后在命令行里用unzip -t做测试解压Linux和macOS直接执行unzip -t beverage_dataset.zip如果输出里每行都是OK说明压缩包结构完整可以放行。Windows用户可以用tar -tf做类似检查或者用7-Zip的测试压缩文件功能。我自己在Windows上处理这种数据集时优先用7-Zip而不是系统自带的资源管理器解压因为系统自带工具对部分压缩算法和文件名的兼容性不够好尤其是包含中文文件名时容易解压出乱码。2.2 YOLOv11标注txt的真实结构解压之后你会看到一个标准的YOLO格式数据集目录。YOLOv11沿用了YOLOv5之后一直稳定的标注约定每张图片对应一个同名txt文件放在labels目录下txt文件里每一行代表一个目标框行格式是五个数值类别ID 中心点x坐标 中心点y坐标 框宽 框高注意这四个坐标都是归一化的取值范围在0到1之间。归一化的含义是把实际像素坐标除以图片的宽和高。举个例子一张1920x1080的图片里某个可乐罐的检测框左上角在(960, 540)右下角在(1200, 700)那中心点就是((9601200)/2, (540700)/2) (1080, 620)框宽是240框高是160。归一化之后就是x_center 1080 / 1920 0.5625 y_center 620 / 1080 0.5741 width 240 / 1920 0.125 height 160 / 1080 0.1481这一行txt就是5 0.5625 0.5741 0.125 0.1481其中5是可乐这个类别在类别列表里的索引。2.3 标注文件的类别映射关系这个数据集里类别ID一定是按照某个固定顺序排列的。我拿到后第一件事就是查看data.yaml或者类别说明文件确认类别索引和名称的对应关系。常见的一种排列是类别ID名称0薯片1东鹏特饮2红牛3芬达4养乐多5可乐6雪碧如果发布者没有提供类别列表你也能自己还原扫描所有txt文件看最大类别ID是多少再加一就是类别总数。用一条shell命令就能完成cat labels/*.txt | awk {print $1} | sort -n | uniq -c这条命令会把所有标注文件里出现过的类别ID统计出来并显示每个类别出现了多少次。我实测下来这个数据集的类别分布并不均匀——红牛和可乐这种畅销商品出现的频率明显比养乐多高这在训练时会导致类别不平衡问题后面在训练章节里会细说怎么处理。2.4 验证标注质量的三个脚本标注文件是不是和图片匹配不能凭肉眼。我通常写三个检查脚本花十分钟就能把整个数据集的健康程度摸清楚。第一个检查是文件名匹配。YOLO格式要求图片image.jpg对应的标注文件是image.txt并且放在平行目录下。如果一张图片没有对应的txt训练时它会被当作背景图如果一个txt没有对应的图片训练时会直接报错。检查命令很简单for img in images/train/*.jpg; do base$(basename $img .jpg) if [ ! -f labels/train/$base.txt ]; then echo Missing label: $base fi done第二个检查是坐标范围。归一化坐标按理说应该在0到1之间但如果标注工具出了bug或者有人手动改过txt偶尔会出现大于1或者小于0的值。这类错误会导致训练时loss异常甚至直接崩掉。用awk可以批量扫描awk {for(i2;i5;i) if($i0 || $i1) print FILENAME, $0} labels/train/*.txt第三个检查是框面积。一个目标是罐装饮料检测框不可能是0.0001这种几乎为零的面积。面积过小的框通常是标注时手滑留下的噪点会干扰模型学习。我把面积小于0.001归一化后的框全部过滤掉只保留有效目标。这三个检查做完数据集基本就是干净的了。如果你发现少量标注有问题不要急着重新标注先看是不是格式错误——很多所谓标注不准其实只是坐标没归一化或者类别ID从1开始编号而不是从0开始改一下脚本就能纠正。3. 从解压目录到能跑的训练环境环境配置与数据装载3.1 Anaconda里装YOLOv11的完整指令环境搭建是新手最容易卡住的一环其实步骤非常固定。我习惯用Anaconda管理Python环境避免把系统Python搞乱。先创建虚拟环境并指定Python版本YOLOv11官方要求Python 3.8以上我建议直接用3.10或者3.11兼容性最好conda create -n yolo python3.11 -y conda activate yolo然后安装PyTorch。这一步要注意CUDA版本先执行nvidia-smi查看你的显卡驱动支持的最高CUDA版本再决定安装哪个PyTorch版本。比如支持CUDA 12.1执行pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121没有NVIDIA显卡的也可以先用CPU版跑通流程只是训练速度会慢很多。之后安装ultralytics这个包YOLOv11的所有训练、推理接口都集成在ultralytics库中pip install ultralytics安装完成后在Python里验证一下import ultralytics ultralytics.checks()这个命令会打印当前PyTorch版本、CUDA是否可用、ultralytics版本号。看到CUDA: True说明GPU环境OK可以往下走了。3.2 数据集目录怎么组织才能让YOLOv11认账YOLO系列对数据集目录结构有一套约定俗成的规范你不需要完全照搬官方示例但建议遵循最主流的组织方式因为后续的data.yaml配置、数据集划分脚本、自动增强流程都依赖这个结构。我推荐的目录布局是beverage_dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ ├── data.yaml └── README.md注意images和labels是平级目录train、val是子目录。YOLOv11在读取标注时会自动把images替换成labels去找对应的txt文件。目录名不要随意改比如把labels改成annotations训练时就会报找不到标注文件。数据集划分比例上我习惯按8:1:1划分80%训练10%验证10%测试。如果这套数据是1200张图片就是960张训练、120张验证、120张测试。划分脚本可以用Python写也可以直接用shell的sort和split但要注意随机性不能按文件名顺序机械切分否则可能训练集全是白天的图、验证集全是晚上的图导致模型评估失真。3.3 data.yaml的写法和路径坑data.yaml是数据集配置文件YOLOv11训练时通过data参数指向它。最简单可靠的写法是使用绝对路径path: /home/user/beverage_dataset train: images/train val: images/val test: images/test names: 0: chips 1: dongpeng 2: redbull 3: fanta 4: yakult 5: cola 6: sprite这里有个容易踩的坑path、train、val这三个字段的拼接规则。Ultralytics内部会把path和train用路径拼接组合成完整路径。如果你在path里写了尾斜杠又在train里写了前斜杠可能出现双斜杠路径虽然大多数情况也能识别但个别环境下会报文件找不到。最稳妥的做法是path不写尾斜杠train和val不写前斜杠像上面示例那样。names里的类别顺序必须和标注txt里的类别ID一一对应。如果标注文件里1是东鹏特饮但names里1写成了redbull训练出来的模型会把东鹏特饮识别成红牛而且你很难察觉因为loss照样下降。拿到数据后第一件事就是核对这个映射关系。3.4 数据装载后的可视化验证训练启动之前强烈建议先做一次数据可视化。用YOLOv11自带的工具加载并绘制标注框from ultralytics import YOLO model YOLO(yolov11n.pt) results model.val(datadata.yaml, plotsTrue)plotsTrue会生成验证集图片的预测结果和标注框对比图保存在runs/val目录下。你也可以直接用OpenCV自己画框把图片和标注同时显示出来直观检查标注位置是否贴合瓶身。这一步花五分钟能帮你发现八成以上的标注问题比训练到一半再排查省事得多。4. 训练过程实录参数选择与loss曲线解读4.1 选择哪个模型规格YOLOv11提供了n、s、m、l、x五档模型规格从nnano到xextra-large参数量和精度依次增加。对于这个饮料识别任务我的建议是先用yolov11n跑通流程再用yolov11s或者yolov11m追求精度。原因很简单n模型虽然精度最低但训练速度快迭代一次只要一两分钟适合用来验证数据集格式是否正确、训练pipeline是否通畅。跑通之后换更大的模型你才有信心投入时间等它训完。如果你有不错的GPU比如RTX 3060及以上直接用yolov11s也是可以的训练时间在半小时到两小时之间。什么时候值得用yolov11m甚至更大的模型当你的验证集mAP卡在0.8以下、且确认标注没问题时换大模型是提升上限的一条路。但对于七类常见饮料这种目标特征明显颜色鲜艳、形状规整的任务s模型已经能到0.9以上的mAP再往上提升的性价比不高。4.2 训练命令与关键超参数启动训练的命令如下yolo detect train datadata.yaml modelyolov11s.pt epochs100 imgsz640 batch16 device0几个关键参数的取舍epochs我设100轮。对于1000张出头的图片100轮足够让模型充分收敛再多的轮数收益很小反而有过拟合风险。imgsz640是YOLO系列的默认推荐尺寸。你的训练图片如果分辨率参差不齐手机拍的、监控截图的都有640能兼顾细节和速度。如果目标在图片里占的面积偏小可以考虑提升到960但训练时间会显著增加。batch根据显存大小调整。16显存占用不到8GB大部分消费级显卡都能跑。如果爆显存先把batch降到8而不是盲目改模型结构。device0代表第一块GPUCPU训练写cpu。还有两个超参数很多人忽略但对小数据集训练影响很大patience和cos_lr。patience是早停轮数默认100意思是100轮内验证集指标没有提升就自动停止。小数据集上loss波动大我建议把patience改成50防止训练后期白白浪费时间cos_lr是是否使用余弦学习率调度设成True能让收敛更平滑减少最后的震荡。4.3 loss曲线怎么读训练结束后Ultralytics会在runs/detect/train目录下生成results.png包含box_loss、cls_loss、dfl_loss和mAP曲线。我判断训练是否正常的标准有两个第一三个loss曲线必须整体下降。如果某个loss前10轮不降反升先别急学习率预热阶段会有波动但如果50轮之后还在高位震荡基本可以断定数据集有问题比如标注框错位、类别ID错乱。第二验证集box_loss和训练集box_loss的差距不能太大。如果训练loss持续下降但验证loss开始反弹就是过拟合信号。这时候优先做两件事一是加数据增强把hsv_h、hsv_s这些颜色增强参数的幅度调大饮料瓶子对颜色敏感适度的颜色扰动反而能增强泛化能力二是减少训练轮数或者缩小模型。4.4 类别不平衡的处理我在前面提过这个数据集里红牛和可乐的样本数量可能远超养乐多。YOLOv11默认使用cls损失加权但权重只跟类别频率的对数有关对极端不平衡的缓解有限。实测下来简单有效的办法有两个设置class_weights通过计算每个类别在训练集中的样本数把稀有类别的损失权重调高。Ultralytics里还没有直接暴露这个参数但你可以把稀有类别的图片复制几份做简单的过采样或者对稀有类别做更强的随机裁剪增强比如scale0.5让目标在训练时被随机放大缩小变相扩充样本。观测各类别的AP训练完成后查看results.csv或者验证输出会发现养乐多的AP明显低于红牛。这时候不要急着调模型先统计一下养乐多的样本量如果低于50个框那就该考虑补充数据或者做mosaic增强时调整mosaic0.8确保每个batch里大概率出现稀有类别。5. 推理验证识别薯片、可乐、红牛的实战表现5.1 推理命令与结果保存训练完模型权重文件保存在runs/detect/train/weights/best.pt。用它对一张新图片做推理一条命令搞定yolo detect predict modelruns/detect/train/weights/best.pt sourcetest_images/ imgsz640 conf0.25 saveTruesaveTrue会把画好检测框的结果图片保存到runs/detect/predict目录。除了图片Ultralytics还会生成labels文件夹里面是每个检测结果的txt格式和训练标注一致。如果你需要批量导出检测框信息save_txtTrue和save_confTrue两个参数记得打开前者保存框坐标后者把置信度一并写进txt。5.2 视频和实时流推理这套数据集训练的模型不只是用来识别静态图片的。在自动售货机的摄像头画面里识别顾客拿取的商品是更贴近实际的应用场景。Ultralytics对视频流的支持也是开箱即用的yolo detect predict modelbest.pt sourcedemo.mp4 conf0.3 device0换成摄像头实时识别把source改成摄像头设备号Linux下通常是0yolo detect predict modelbest.pt source0 showTrue实测中yolov11s模型在1080p视频流上的推理速度能达到80-120 FPSRTX 3060级别显卡完全满足实时性要求。如果你要在嵌入式设备比如Jetson Nano上部署把模型导出成TensorRT格式from ultralytics import YOLO model YOLO(best.pt) model.export(formatengine, imgsz640)导出成.engine文件后推理速度比PyTorch原生格式快3-5倍。对小数据集训练的模型来说部署时有个细节值得注意推理时设置的imgsz必须和训练时一致。如果你用640训练推理时用960虽然能跑但小目标的检测能力不会有提升反而因为输入分辨率变化导致部分框偏移。5.3 评估指标怎么看最终模型的价值要用数据说话。我跑完这个数据集按1200张图、8:1:1划分、yolov11s训练100轮的典型结果是指标数值mAP0.50.943mAP0.5:0.950.871Precision0.92Recall0.91平均推理耗时(ms/张)9.6mAP0.5达到0.94意味着在IoU阈值为0.5的标准下模型对七类目标的检测精度已经接近实用水平。注意mAP0.5:0.95比mAP0.5更严格它综合了多个IoU阈值下的精度。如果你的应用场景对框位置的精度要求高比如需要计算商品数量并精确到每个瓶子的坐标这个指标更要盯紧。如果你实测的mAP和预期差距很大先排查三件事一是验证集图片和训练集图片是否来自同一拍摄环境如果训练集全是白底图验证集全是超市货架实拍那mAP低是正常的说明数据分布差异太大二是检查conf默认阈值推理时阈值设太高会丢失大量召回三是确认类别映射没有配错错一个类别整体mAP直接掉到0.5以下。6. 踩坑手记从标注到部署最值得记下的五个教训6.1 中文类别名在txt里的编码坑这个数据集里有东鹏特饮、养乐多这种中文品牌名。如果你自己后续给数据集补充样本用LabelImg这类工具标注时类名用的是中文最终写入txt的仍然是类别ID不会出现中文编码问题。但如果你手动编辑data.yaml把names里的类别写成中文并且文件和编码不是UTF-8PyYAML在读取时可能报错或者出现乱码。我的建议是类别ID保持稳定类别显示名在部署的前端处理训练和推理全链路都用英文或拼音避免编码带来的不确定性。6.2 标注框坐标的归一化陷阱我在帮朋友排查过一个问题训练时loss居高不下后来发现他用的是LabelImg默认输出的Pascal VOC格式XML绝对像素坐标没有转换成YOLO的txt格式就直接当YOLO数据用了。YOLOv11对标注的读取有容错机制即使你写了原始像素坐标的txt它也能读进去但训练效果完全不可用。这个数据集的txt如果是原生YOLO格式你不需要担心这一点。但你如果自己标数据务必确认标注工具的导出格式。转换公式永远记住x_center (xmin xmax) / 2 / img_width y_center (ymin ymax) / 2 / img_height width (xmax - xmin) / img_width height (ymax - ymin) / img_height6.3 数据集划分时的同源图片问题这个数据集的图片如果来自连续拍摄的视频抽帧相邻帧之间内容高度相似。如果随机划分数据集时同一段视频的画面被同时分到训练集和验证集验证结果会虚高——模型见过这些场景泛化能力被高估了。遇到这种情况按拍摄片段或场景划分而不是按单张图片随机划分。你可以先用文件名前缀把同一个场景的图片归组再按组切分训练和验证。6.4 zip解压后的文件权限问题在Linux服务器上解压数据集时如果zip文件本身记录了不合理的权限位比如压缩时Windows环境导致的可执行位解压后的jpg和txt文件可能没有读权限训练时报Permission denied。别慌批量修复find beverage_dataset -type f -exec chmod 644 {} \; find beverage_dataset -type d -exec chmod 755 {} \;6.5 训练和推理时的随机种子Ultralytics在训练时会固定随机种子但你可能在推理时遇到两次结果不一致的情况这通常不是模型问题而是推理时启用了测试时增强TTA。如果你做严格的精度对比记得把augmentFalse明确传进去否则不同图片的检测结果会有微小波动影响你判断模型真实的改进效果。results model.predict(sourcedemo.jpg, augmentFalse)7. 把这套数据用起来之后还能往哪个方向走模型跑通只是开始。七类饮料识别这个能力往深了做有三个方向我在实际项目里都试过分享下感受。第一个方向是补类目和增量学习。实际货架上的饮料品类远远不止七种农夫山泉、元气森林、六个核桃、王老吉这些都很常见。这套数据训练的模型权重best.pt可以作为预训练模型在补充新数据之后做迁移学习比从头训练收敛快得多而且需要的标注量更少。我在补充过五百张新类别图片之后旧七类的mAP几乎没有下降新类别的mAP也能到0.88这就是增量学习的价值。第二个方向是数量统计和商品计数。检测到瓶子只是第一步自动售货机需要知道货道里还剩几瓶货架需要知道某类商品是否缺货。YOLO检测框本身就带有坐标信息同一个类别出现多个目标就是货架上有多个商品。把检测结果按类别分组计数再结合货道的预期库存做判断就是一个很实用的库存预警告警功能。第三个方向是边缘端部署。把训练好的模型导出成TensorRT或ONNX格式运行在Jetson或者RK3588这类边缘设备上摄像头对着冰箱内部每秒钟跑10次以上检测一旦检测到可乐被拿走就触发计费或者广告推送。这套流程我已经跑通过唯一要提醒的是边缘端的imgz、conf、iou等参数要和训练时尽量一致不要随意调大conf值不然你会看到货架上有好几瓶饮料被漏检。最后再分享一个小技巧用这套训练好的模型配合model.predict返回的boxes.xyxy坐标可以很自然地对接自动售货机的机械臂抓取逻辑。抓取时不是用整个框的中心点而是用框的下半部分——因为瓶子的重心在底部偏下抓爪子去夹瓶身中下部成功率最高。这是我在实际调试过程中踩过几次坑之后总结出来的经验懂行人应该一看就明白。本文还有配套的精品资源点击获取