可回收废物检测数据集:从YOLOv5到YOLOv8的训练实战与避坑指南
简介面向YOLO系列目标检测开发者这份可回收废物检测数据集涵盖玻璃瓶、纸瓶、塑料瓶、塑料袋四类常见废弃物包含完整标注与训练/验证集划分可直接用于yolov5至yolo11等主流版本模型的训练与效果验证。压缩包约230MB共2000个标注文件VOC格式xml与YOLO格式txt并存分别置于独立文件夹坐标均按图像归一化处理满足不同框架的读取习惯。数据集图像总量达6000张覆盖室内外多种场景可支撑垃圾分类、智能回收终端等落地项目的模型迭代。目前已有47人学习下载适合需要高质量真实样本进行算法调优的研究者与工程师省去自行采集和标注的时间成本快速验证模型在可回收物分类场景下的表现。1. 可回收废物检测数据集6000张图够不够训练一个能上线的模型先说结论6000张图对于玻璃瓶、纸瓶、塑料瓶、塑料袋这四类可回收废物来说不是“够不够”的问题而是“能训练到多稳定”的问题。只要标签质量没问题、背景足够多样用yolov5或yolov8从零训练mAP0.5做到0.9以上是正常水平放到实际分拣场景里跑个实时检测完全够用。这个数据集我拆完后的第一印象是它已经划分好了train/val/test两种标签格式yolo的txt和voc的xml都齐全等于省掉了数据准备阶段最烦人的两步——标注转换和数据集划分。刚接触yolo系列算法的朋友可以直接拿它练手做毕设、做课程设计、做垃圾分类原型都合适有经验的工程师则可以把重点放在训练参数调优和模型部署上不用在数据清洗上浪费时间。2. 数据集的真实构成标签格式、目录结构与模型选型逻辑2.1 两种标签格式并存yolo的txt与voc的xml各自解决什么问题这个数据集最值得说的不是6000张图的规模而是它同时提供了两种标签格式。项目里的xml文件是典型的Pascal VOC标注文件名像 img_067_686.xml、img_067_3869.xml 这样按图片文件名一一对应。xml里记录的是完整的目标框信息包括图片尺寸、目标类别名、bndbox的原始像素坐标。这种格式的好处是“人类可读”用labelImg这类标注工具打开就能继续编辑适合做二次标注或者人工校验。txt文件则直接是yolo训练时吃的格式每一行对应一个目标框五个数字分别是类别索引、中心点x、中心点y、框宽、框高全部是相对于图片宽高的归一化比例值范围0到1。这种格式是yolo系列算法统一要求的输入格式yolov5、yolov7、yolov8、yolov9、yolov10、yolo11全部通用不需要转换解压之后放进数据目录就能开训。两种格式并存的意义在于互补训练时用txt因为训练代码读取效率高、不涉及坐标转换人工核对或者可视化调试时用xml因为能看到“这个框是猫还是狗”的文本描述而不只是数字。常见做法是先用xml做校验确认无误后用转换脚本批量生成txt。这个数据集已经把两边都给你准备好了省掉了最容易出错的一步——手工转换时把归一化坐标算错。2.2 标注字段逐项拆解中心点坐标与宽高比例不能搞反先看yolo格式的txt文件一行内容的基本结构是0 0.514062 0.398148 0.282813 0.271296这行数字的含义是目标类别是索引0对应数据集里排在第一位的类别目标框中心点位于图片宽度方向的51.4%、高度方向的39.8%处框宽度占整张图片宽度的28.3%框高度占整张图片高度的27.1%。训练代码读取时只会按这个顺序解析不会帮你判断哪个数字代表什么所以顺序不能错。xml文件的bndbox节点里存的是原始像素坐标bndbox xmin263/xmin ymin180/ymin xmax444/xmax ymax326/ymax /bndbox从xml转yolo格式时核心计算逻辑是这样的x_center (xmin xmax) / 2 / image_width y_center (ymin ymax) / 2 / image_height width (xmax - xmin) / image_width height (ymax - ymin) / image_height这段转换逻辑是最容易翻车的地方。x_center必须用(xminxmax)/2求得像素中心点后再除以图片宽度width直接用(xmax-xmin)除以图片宽度。很多新手会把x_center写成xmin / image_width或者忘记除以图片宽高导致训练出来的模型预测框全部偏在图片左上角。我每次拿到新的标注数据都先写个脚本抽查十几行txt对应到原图上画框验证确认没算错才敢开训。2.3 目录结构与类别顺序为什么拿到就能直接用而不只是噱头数据集的目录划分是直接对标yolo训练规范的我拆包后看到的目录结构基本是dataset/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ (txt格式) │ ├── train/ │ ├── val/ │ └── test/ ├── voc_xml/ (xml格式) │ ├── train/ │ ├── val/ │ └── test/ ├── classes.txt └── dataset.yamltrain/val/test三个子目录已经按比例切好不用再写脚本去random拆分。训练前只需要确认一件事xml里object的name字段和txt里类别索引的对应顺序是否一致。比如xml里写的是glass_bottle如果它在类别列表里排第0位那txt里对应就是0paper_carton排第1位txt里就是1。这个对应关系一旦错位模型训练过程不会报错但预测结果会张冠李戴——检测到玻璃瓶却显示成塑料瓶这类错位问题在训练阶段不会暴露验证集里才看得出来。关于模型选型我的建议是当前数据规模用yolov5s或yolov8n起步就够了6000张图四分类不算大不需要一上来就上yolov5x或yolo11x这种大模型。深度越大的模型在这个量级的数据上容易过拟合训练时间翻倍收益却很小。先把小模型跑到收敛确认数据没问题再根据需要换大模型或者做剪枝这个思路更稳妥。3. 用yolov5把数据集跑起来环境准备到训练完成的全流程3.1 环境准备与文件清单核对少一个labels子目录都白搭先假设你用的是yolov5官方仓库。完整训练流程的第一步不是装环境而是核对文件。解压之后先确认images和labels两个目录下的train/val/test子目录齐全再检查每一张jpg或png图片都能找到对应的txt标签文件。检查脚本不用写太复杂一条bash命令的事for img in images/train/*.jpg; do base$(basename $img .jpg) if [ ! -f labels/train/$base.txt ]; then echo Missing label for $img fi done这段脚本做的事情是遍历images/train目录下每张jpg图片提取不带扩展名的文件名去labels/train目录找同名txt标签文件找不到就打印提醒。跑完之后没有任何输出说明图片和标签是一一对应的可以放心继续。做完这一遍我还会抽查五六个txt文件确认里面不是空文件。空标签会让yolo训练时忽略对应图片但这种忽略是“软忽略”不会报错只会让你实际参与训练的图片变少模型泛化能力打折扣。安装依赖时注意一点yolov5仓库的requirements.txt里锁定的torch版本比较老如果你的机器是新的CUDA环境建议直接装新版torch再装其他依赖避免torch版本冲突导致模型训练时GPU利用率上不去或者报CUDA初始化错误。3.2 数据集配置文件与训练参数设置yaml文件决定了这次训练的对错yolov5训练前需要准备一个data.yaml文件这个文件告诉训练代码去哪里读图、标签有哪几类。内容如下train: ./dataset/images/train val: ./dataset/images/val test: ./dataset/images/test nc: 4 names: [glass_bottle, paper_carton, plastic_bottle, plastic_bag]train、val、test三个路径指向图片目录yolo会自动在相同路径下把images替换成labels来定位txt标签。nc必须和names列表长度一致这个数据集是四类所以nc填4。names的顺序就是类别索引顺序第0个名字对应txt里所有类别索引为0的目标。如果你把names顺序写错比如把plastic_bag放到第0位那么训练出来的模型会把所有玻璃瓶都识别成塑料袋而且loss值照样降得很漂亮——这个错不看混淆矩阵基本发现不了。训练命令根据你的机器显存来调整参数python train.py --img 640 --batch 16 --epochs 150 --data dataset.yaml --weights yolov5s.pt --name recyclable_run参数含义--img 640表示训练输入图片尺寸缩放为640x640这是速度和精度之间的常用平衡点--batch 16是每批训练的图片数量取决于显存大小8GB显存跑16张640x640图片比较极限不够就降到8或4--epochs 150是训练轮数这个数据量下100轮基本收敛150轮是为了看透loss曲线的尾巴--weights yolov5s.pt是从预训练权重开始迁移学习不指定的话就完全从零训练收敛速度会明显更慢。跑起来之后盯着loss曲线看就行train和val两条曲线都逐渐下降并趋于平稳就是正常的。3.3 训练验证与测试从weights到实际检测效果的最后一段路训练结束后yolov5会在runs/train/recyclable_run目录下生成best.pt和last.pt两个权重文件。best.pt是验证集上mAP最高的权重last.pt是最后一个epoch保存的权重实际部署时只用best.pt。先用验证集看一眼模型效果python val.py --data dataset.yaml --weights runs/train/recyclable_run/weights/best.pt --img 640val.py会输出各类别的precision、recall和mAP0.5、mAP0.5:0.95两个核心指标。对四分类回收废物检测来说mAP0.5超过0.9算合格超过0.95说明数据质量和训练都到位了。mAP0.5:0.95到0.7以上说明框的定位精度不错这个指标本身比较苛刻過度追求会逼着加大模型或者调高IoU阈值实际部署时意义不大。最后拿一张没参与训练的真实照片做推理测试python detect.py --weights runs/train/recyclable_run/weights/best.pt --source test_image.jpg --conf-thres 0.4--conf-thres 0.4表示只有置信度超过40%的预测框才会被画在输出图片上。如果检测结果里出现大量框在目标物上但置信度只有0.1、0.2的情况说明模型没学透优先检查数据集本身的问题而不是调低阈值硬撑。4. 从yolov5迁移到yolov8换模型不换数据的关键调整4.1 yolov8的目录与格式要求结构没变但细节有差异yolov8训练时对数据目录结构的要求跟yolov5几乎一模一样同样是images和labels两个顶层目录train/val/test分开txt标签格式完全相同。也就是说这个数据集解压后不需要做任何转换直接就能喂给yolov8。但有几个细节差异必须知道。第一个差异是yaml配置文件里的类别列表格式略有不同yolov8对names部分的要求更严格推荐写成字典形式path: ./dataset train: images/train val: images/val test: images/test nc: 4 names: 0: glass_bottle 1: paper_carton 2: plastic_bottle 3: plastic_bag我建议大家如果要用yolov8就把yaml改写成这种格式。这样names后面的数字索引就和txt里的类别索引完全显式对应了排查类别错位问题的时候一眼就能看出来。第二个差异是yolov8内部自动做了mosaic增强等预处理不需要手动配置epochs和batch参数直接写在命令行里整体更简洁。4.2 yolov8训练命令与参数详解命令行比配置文件更直接yolov8的CLI训练命令不需要写python脚本直接一行搞定yolo detect train datarecyclable.yaml modelyolov8n.pt epochs150 batch16 imgsz640 device0几个关键参数说明modelyolov8n.pt是nano版本预训练权重参数最少、推理最快适合在6000张图这个量级上先行验证想追求更高精度可以换成yolov8s.pt或yolov8m.pt但在这个数据量上提升有限训练时间却会成倍增加。device0指定用第一块GPU训练没有GPU就填cpu但训练速度会慢几十倍400张图的epoch跑起来会很煎熬。训练过程中yolov8会在控制台实时打印每个epoch的box_loss、cls_loss、dfl_loss以及precision、recall、mAP这几个指标。它的loss曲线变化趋势和yolov5不太一样yolov8的cls_loss下降得更快因为分类分支的损失权重设计不同看到类别损失前20个epoch就降得很低不要慌这不是bug。训练结束后权重保存在runs/detect/train/weights/best.pt用下面的命令验证yolo detect val datarecyclable.yaml modelruns/detect/train/weights/best.pt batch16yolov8的val命令会自动输出混淆矩阵和PR曲线到runs/detect/val目录打开confusion_matrix.png看一眼就能确认类别是否有错位。对四分类数据集正常情况是主对角线四个格子颜色最深其余位置接近黑色。如果发现某一列有明显亮块说明这个类别的样本被大量误判成了其他类然后回到标注数据里检查该类别的框有没有标错。4.3 导出部署格式从yolov8权重到onnx再到实际项目集成训练完模型的下一步常规操作是导出成onnx格式方便后续接入TensorRT或者OpenCV DNN部署。yolo格式的txt标签和yolov8导出的模型完全兼容不需要再处理标注。yolo export modelruns/detect/train/weights/best.pt formatonnx imgsz640导出后可以用onnxruntime在Python里做推理测试不依赖yolo框架。如果导出时报错提示opset版本不支持加上opset12参数重试。onnx是部署环节的中间态用它接后端服务或者嵌入式设备都很方便这也是工业落地时最常见的做法。5. 避坑手册标签错乱、类别遗漏与训练异常的排查记录5.1 xml和txt坐标对不上可视化画框偏到角落现象用脚本把txt标注画到原图上发现检测框的位置明显不对有些框跑到图片左上角有些框大小异常。原因xml转txt时没有按图片实际宽高做归一化或者转换公式里(xmax-xmin)和(xminxmax)/2用反了。解决写个python脚本读取原图尺寸按2.2节列出的公式重新计算一遍然后把新生成的txt覆盖到labels目录。我在处理别的数据集时遇到过更隐蔽的情况图片尺寸在标注后被批量缩放但xml里的像素坐标没同步更新这种只能重新转。5.2 训练日志提示图片和标签数量不匹配现象训练启动时控制台打印的图片数量比标签数量多几百张或者反过来。原因images目录下存在非图片文件或者标注过程中有些图片漏标了但文件被yolo框架忽略处理了。一般是先检查images和labels两个目录下的basename集合是否完全一致。用下面的命令直接找出差异diff (ls images/train | sed s/\.[^.]*$// | sort) (ls labels/train | sed s/\.[^.]*$// | sort)这个命令先用sed去掉扩展名再排序最后用diff比较两边差异。有输出就按输出结果补齐或删除多余文件没输出说明数量是匹配的。平时训练任何数据集我都会在开始前跑这一遍这属于最基础的自检动作。5.3 混淆矩阵里某一列或某一行特别亮现象模型训练完成mAP指标也正常但混淆矩阵显示某个类别被大面积误判成另一个类别。原因两个类别之间标注边界严重重叠或者目标本身外观太接近。最常见的具体原因是塑料瓶和玻璃瓶两种目标在图片里都是透明或半透明的标注员把框画得过大把背景也圈进去了导致模型分不清两个类别的真实特征。解决先可视化抽查这些类别的标注框如果框确实包含大量背景把标注框收紧重新训练。如果检查后发现标注没问题就要考虑从数据层面增加这些目标的特写截图或者把这几个混淆严重的类别的loss权重调高一些。5.4 loss曲线不下降或训练早期出现NaN现象训练进行到第20个epochbox_loss还在3以上cls_loss几乎没有变化或者loss直接变成NaN导致训练中断。原因学习率设置过高、batch size太小导致梯度震荡、图片中存在全黑或全白样本干扰归一化、标签文件里出现超出0到1范围的坐标值。先说一套最直接的排查流程先用下面命令检查标签数据合法性awk {if ($20 || $21 || $30 || $31 || $40 || $41 || $50 || $51) print $0} labels/train/*.txtawk命令会遍历所有txt标签找出任何一个坐标值越界的行并打印出来。这条命令有输出说明标签数据确实有问题把那行对应的图片找出来重新标注即可。如果标签数据没问题就检查训练初始学习率yolov5默认0.01对大多数情况都适用但如果你用的是更大batch size建议按比例把学习率降到0.005左右再试。NaN问题常见于使用fp16训练时如果确认数据没问题加一句--no-half参数强制用fp32精度训练能稳定很多。5.5 验证集mAP为0或验证时类别数不匹配现象训练过程一切正常val.py跑完之后打印的mAP全是0或者直接报错说类别数量对不上。原因data.yaml里的nc和names数量不一致或者验证集的label文件里出现了训练时没见过的类别索引。最典型的例子是标签文件里混入了类别索引5但data.yaml里只定义了0到3四类。解决方法是先运行下面的命令找出所有可能超范围的标签grep -E ^[^4-9] labels/val/*.txt || echo all labels within range这个命令的逻辑是匹配行首数字大于4的标签行。如果输出内容就说明val目录下有非法类别索引。此类错误通常是个别图片标注时用错了类别Id找到对应txt文件修改后重新训练。如果不想重新训练也可以直接在data.yaml里把names列表补足到索引5但这种做法会导致新类和原有类别共用同一个权重分支部署时预测结果混乱不建议这样处理。6. 数据集质量的检验技巧从图片样本到mAP曲线的自检方法拿到数据集后不要急着开训先花一两个小时把所有图像按类别随机抽出来用python画一批可视化图直接目测一遍标注框和真实物体的贴合程度。我的习惯是每个类别随机抽200张图把框画出来存成一个拼图文件从头翻一遍。这一步看起来土但暴露问题最快——标注框是否偏大、是否有漏标目标、类别是否有标错的肉眼一目了然。这个过程还能顺手验证txt标签的坐标是否和xml保持一致一举两得。训练完成之后做二次验证标准动作是从不方便公开的场景里挑几张新的未标注图片用训练好的模型跑一遍推理看检测框的置信度和位置是否稳定。然后进一步做抗干扰测试。第三步验证的是模型的稳定性正常安排是拿测试集跑一组不同置信度阈值下的指标。yolo框架训练完默认用conf-thres 0.25做验证但实际部署时阈值往往要调高。分别用0.25、0.4、0.5、0.6跑一遍测试集对比precision和recall的变化曲线。阈值升高时precision会上升、recall会下降找到一个平衡点是部署调参的关键动作。如果阈值从0.25升到0.5时recall断崖式下跌说明模型对目标特征的学习还不够充分优先回到数据层面补强而不是硬调阈值。从那次之后我每次拿到新数据集都强制自己先走一遍上面说的流程跑完才敢决定要不要继续往下训练或部署。很多翻车现场都发生在“看着指标不错一上真实场景就崩”的瞬间前期的数据质量检查能帮你避开大部分这种尴尬。希望这些经验能帮你在自己的项目里少走一段弯路。本文还有配套的精品资源点击获取