简介YOLO垃圾四分类数据集提供可回收垃圾、有害垃圾、厨余垃圾和其他垃圾四类目标的YOLO格式标注文件聚焦垃圾分类场景下的目标检测训练需求适合算法工程师、高校学生及智能环保项目开发者使用。压缩包共包含2000个文件其中1999个txt标注文件对应每张图像的类别与边界框信息1个yaml配置文件用于定义数据集路径、类别名称和数量整体大小约540.75MB解压后可直接接入YOLO系列训练流程。目前已有2088人浏览学习适合用于构建垃圾分类识别模型、训练目标检测网络或验证数据增强策略。借助这套数据可快速完成数据划分与模型迭代降低自行采集和标注成本同时为搭建自动分类回收系统、智慧环卫终端或教学实验提供真实可靠的样本支撑。1. YOLO 垃圾四分类数据集拿到手先别训练先拆这三处细节一份 YOLO 垃圾四分类数据集拿到手常规动作是解压、翻几张缩略图、直接开始跑训练。某开发者在楼宇智能分类项目中第一版模型对牛奶盒的识别率一直上不去调了两周参数没有进展换成这份数据集重训后半天就定位出问题不是网络结构不对而是数据里藏着类别错位和标签边界问题。这份资源主体是四分类图像与标准 YOLO txt 标注覆盖可回收物、厨余垃圾、有害垃圾、其他垃圾图片和标签按目录配对。适合正在做目标检测项目、想省掉收集和清洗时间的人。但在点下训练按钮之前先把目录映射、类别编号、样本均衡三件事拆干净能省后面一整周的返工。2. 拆包与标注校验txt 格式、文件映射和类别分布这份资源按目标检测数据集组织不是分类数据集这一点从 labels 目录里的 txt 就能看出来。四分类垃圾的真实场景中一张图里经常同时出现矿泉水瓶、易拉罐、外卖盒多个目标整图打一个类别标签满足不了需求所以标注采用了 YOLO 的归一化边框格式。在开始训练之前先验证数据完整性和格式合法性这一步花二十分钟后面能少踩一半的坑。2.1 目录结构先打印一棵树再核对图片与标签的同名映射拿到数据包先不急着看内容用 find 或 tree 把整体结构打出来确认是 train/val 子目录切分还是 images 平铺之后用列表文件索引。这份资源通常会把 train 和 val 切好但我一般会再生成一份完整的 train.txt / val.txt 列表方便后续做数据筛选或转成其他框架格式时使用。tree -L 2 garbage4/ # 预期看到两个一级目录images/ 与 labels/ # 每个下面再有 train/、val/ 子目录或平铺后用 train.txt 索引如果环境里没有 tree用 find 替代find images -name *.jpg | wc -l find labels -name *.txt | wc -l两个数字对不上说明存在缺标签的图片或者存在没有对应图片的孤儿 txt。缺标签的图在训练中会被跳过但如果比例超过 3%模型容易在部分类别上学不到完整特征。两边数量一致也不代表万事大吉还必须按文件名做一一配对校验写成脚本执行最可靠from pathlib import Path img_dir Path(garbage4/images/train) label_dir Path(garbage4/labels/train) imgs {p.stem for p in img_dir.glob(*.jpg)} labels {p.stem for p in label_dir.glob(*.txt)} missing imgs - labels orphan labels - imgs print(f缺标签的图片数量: {len(missing)}) print(f无图像的孤儿标签: {len(orphan)}) for name in sorted(missing)[:10]: print(f missing label: {name})这段脚本用 stem 提取不含扩展名的文件名做交集差集YOLO 要求图片与标签同名才能配对。glob 的匹配后缀要按实际格式调整数据集里图片也有可能是 png 或 bmp那就把*.jpg改成*.png或者干脆用img_dir.iterdir()遍历全部文件再筛扩展名。缺标签的图片常见原因是标注时图片压缩失败或者中间有人手动删过文件处理方式不是简单补齐而是先看是极个别漏网还是成序列丢失成序列丢失往往意味着原始采集目录乱掉了需要回到源头核对。2.2 YOLO txt 标注格式五个字段的含义必须心里有数labels 目录下任何一个 txt 打开内容是这样一行1 0.3452 0.6187 0.2201 0.2714第一个数字是类别编号从 0 开始后面四个是归一化坐标。这份四分类数据集里类别编号的定义如下表训练前的第一件事就是把编号和类名对应关系打印出来贴到显眼位置编号类名说明典型误判对象0recyclable可回收物塑料瓶、易拉罐、纸箱1kitchen_waste厨余垃圾果皮、剩饭、菜叶2hazardous有害垃圾电池、过期药品、灯管3other其他垃圾脏纸巾、陶瓷碎片、一次性餐具坐标字段的顺序依次是class x_center y_center width height中心点和宽高都是归一化值范围 0 到 1 之间。具体含义如下表字段含义有效范围class类别编号0~3x_center框中心点横坐标 / 图片宽0~1y_center框中心点纵坐标 / 图片高0~1width框宽度 / 图片宽0~1height框高度 / 图片高0~1归一化意味着标签跟图像分辨率绑定同一份标注在 640 和 1280 下都成立这也是 YOLO 格式在这方面最省心的原因。但需要注意真实采集场景中图像比例不是固定的如果图片有横向有竖向归一化到 0~1 后没有 EXIF 旋转问题相对省心一旦出现某个框的 width 或 height 大于 1说明坐标归一化时分母用错了这是后面训练精度上不去的常见根源。2.3 类别平衡度检查四分类不均衡是天然存在的先量一量垃圾四分类数据集的分布天然是不均衡的厨余垃圾和其他垃圾容易收集有害垃圾在生活场景中占比很少。不均衡不需要恐慌但需要知道到底不均衡到什么程度用一个脚本统计各类别框的总数import collections from pathlib import Path boxes collections.Counter() files collections.Counter() for p in Path(garbage4/labels).rglob(*.txt): lines [ln.strip() for ln in p.read_text().splitlines() if ln.strip()] if not lines: continue files[p.stem] len(lines) for line in lines: cls int(line.split()[0]) boxes[cls] 1 for cls in range(4): print(fclass {cls}: {boxes.get(cls, 0)} boxes) print(f空标签文件数量: {sum(1 for v in files.values() if v 0)})rglob(*.txt)递归找 labels 下所有标注文件逐行取第一个字段做统计。collections.Counter在这里比手写 dict 方便遇到不存在的键不会报 KeyError。空标签文件要单独记录YOLO 训练允许空文件存在代表这张图没有目标但如果空标签集中在验证集mAP 会被拉低。类别比例超过 5:1 时最低的两个类别单独看 AP 会明显偏低。处理不均衡有几种常见手段一是对少数类做增强比如无害的亮度扰动和随机旋转二是把少数类图片在数据集中重复几次简单但风险是模型过拟合三是训练时把少数类 mAP 作为主要观察指标而不是只看整体 mAP50。数据量差距在 3 倍以内通常不做特殊处理先直接跑基线再决定。提示拆包时如果发现 train 和 val 目录下类别分布差异很大比如有害垃圾只在 val 中出现请先重新划分数据集否则验证指标的参考价值非常有限。3. 训练配置与参数data.yaml、imgsz、batch 的选择逻辑这份数据集的标注格式与 YOLOv5、YOLOv8 完全兼容训练前只写一个 data.yaml 即可。这一章把配置、命令和训练日志的读取方式完整说清楚每个参数都给出调整方向方便按自己机器实际显存做取舍。3.1 data.yaml路径、类别名与编号必须严格对应data.yaml 是数据集与模型之间的桥路径写错会直接报错类别名写错则训练能跑但是结果全乱。按四分类数据集写的标准配置如下path: /home/dev/garbage4 train: images/train val: images/val names: 0: recyclable 1: kitchen_waste 2: hazardous 3: otherpath建议写绝对路径。YOLOv8 的path是相对当前工作目录解析的如果在项目根目录下执行命令相对路径要写成./garbage4换一台机器就要改一次。写绝对路径可以避免这类环境迁移问题但代价是代码库换个仓库路径就要同步改配置。train和val是相对于path的子路径不要加上/home/dev/前缀。names的字典顺序没有作用真正起作用的是键名 0~3它必须和 txt 文件里的第一个字段一致。如果标注里1代表可回收物而 yaml 里1是厨余垃圾训练不会报任何错误推理结果则会整体错位。检测场景中类名建议用英文小写加下划线中文类名也能用但导出 ONNX 后在部分推理框架里会出现编码乱码。3.2 训练命令从 YOLOv8s 起步backbone 尺寸不要一上来就选大的四分类垃圾目标不算小类别间外形差异也明显s 级模型在这个任务上是性价比最高的起点。直接从 x 级模型开始练训练时间拉长验证精度的提升往往不超过两个点但部署体积翻了几倍。yolo train modelyolov8s.pt \ datagarbage4.yaml \ epochs200 imgsz640 batch16 \ patience50 \ projectruns/train_garbage4 \ namebaseline_v1各参数的选择逻辑如下表参数起步值调整方向modelyolov8s.pt精度不够再上 m显存紧张用 nepochs200小数据集 100 足够大数据集 300imgsz640目标普遍偏小再上 960batch168G 显存降到 8加梯度累积到等效 16patience50数据集大、epochs 多时可以放宽到 80patience50是关键参数表示验证集指标连续 50 个 epoch 没有提升就早停。这个任务不会用到 200 个 epoch一般 80~120 之间就收敛早停能省掉大量无效训练时间。关于imgsz不要盲目上 1280检测框小的时候提高分辨率有效但显存占用是平方级增长很多情况下先用 640 跑通再用 960 对比一次看 mAP 提升是否值得。如果目标框在图片中确实很小比如远处的小药瓶那么优先用 960 或 1280 输入同时配合 mosaic 增强效果比换大模型更明显。batch 大小影响收敛稳定性batch 过大时 BN 层统计量更稳定但对小数据集来说 16 与 32 的最终差异很小如果显存只够 8用梯度累积把等效 batch 补到 16。3.3 results.csv训练过程中真正该盯的几列训练过程中很多人习惯盯着终端刷新的 loss 数字焦虑其实那些数值无法直接说明模型好不好。YOLO 训练会自动在项目目录下生成 results.csv这是判断训练状态的权威依据import pandas as pd df pd.read_csv(runs/train_garbage4/baseline_v1/results.csv) cols [epoch, train/box_loss, val/box_loss, metrics/mAP50(B), metrics/mAP50-95(B)] available [c for c in cols if c in df.columns] print(df[available].tail(10))val/box_loss是最需要盯的列。训练前期 train loss 和 val loss 一起下降是正常当 train loss 还在降、val loss 开始回升时模型进入过拟合阶段此时 best.pt 已经保存在早停触发前的位置不需要手动回滚。四分类这种数据量适中的任务mAP50 是最具参考价值的指标mAP50-95 对框的位置精度更敏感如果泛化到实际场景后发现框偏大或偏小重点看 mAP50-95 而不是 mAP50。另外注意YOLO 每次训练自动递增项目目录同一个 project 名下第二次训练会在末尾加序号不要手动删掉上一次的训练结果后面画对比曲线还要用到。4. 避坑指南五个高频翻车现场和排查办法数据集本身质量问题的表现往往不是训练报错而是训练过程顺利但精度不达标。这一章整合五个最典型的问题场景每条按现象、原因、解决三个层次说明全部是从实际项目中筛出来的高频情况。4.1 坑一标注数据里类别编号写成 1 到 4配置却按 0 到 3 读现象训练过程无比顺利loss 正常下降mAP50 达到 0.92但把模型接到摄像头预览里每次把可回收物识别成有害垃圾类名错位非常规律。原因标注工具导出时部分标注人员习惯从 1 开始编号txt 里第一个字段被写成 1~4。而 data.yaml 里 names 键是 0~3模型训练时 class4 虽然没有在 yaml 中被定义但数据集内部类别定义和模型输出层之间发生了整体偏移。YOLO 训练不会对 class 编号做合法性校验没有显式定义 classnc 的检查逻辑因此这种错误会全程静默。解决在训练前增加一步强制校验扫全部 txt 的 class 字段必须落在 0~3 区间内from pathlib import Path import sys bad_files [] for p in Path(garbage4/labels).rglob(*.txt): for i, line in enumerate(p.read_text().splitlines()): cls int(line.split()[0]) if cls not in (0, 1, 2, 3): bad_files.append((p, i 1, cls)) if bad_files: print(f发现 {len(bad_files)} 个非法类别编号) for p, lineno, cls in bad_files[:20]: print(f {p}: line {lineno}, class{cls}) sys.exit(1)把这段脚本放在训练前强制执行而不是等模型训练完再去推理测试能直接拦截掉这一类错位问题。发现是从 1 到 4 的偏移后批量把 txt 中所有 class 数字减 1 即可不要手工改用脚本批量处理并重新打印一遍各类别统计确认。4.2 坑二一张图里有多个目标标注只框了最明显的那个现象mAP50 在 0.85 左右但实际场景中模型总能预测出图上没有标注过的目标或者在多目标图片里只输出一个大框。原因数据集的采集依赖人工标注在时间紧张的情况下标注人员往往只框出画面中央或亮度最高的目标漏掉角落里的透明水瓶、暗色易拉罐。漏标与错标不同错标是模型学偏漏标是模型被错误地训练成“看到某个物体时不应该输出检测框”。验证集指标不会直接暴露这个问题因为漏标的图片在计算 mAP 时不会计入假阳性它的危害隐藏得很深。解决用训练好的模型对所有训练图片做一次批推理输出去重后的候选框把置信度大于 0.5 但和真实标签 IoU 小于 0.3 的检测结果输出成图片人工快速扫一遍。这类漏标图片通常集中在特定场景比如桌面俯拍或者夜间光源环境。注意漏标问题的本质是训练信号不完整靠调参数解决不了。一次漏标排查批量生成的负样本图通常能发现 5%~10% 需要补标注的图片。4.3 坑三验证集里出现训练集图片指标虚高形成假象现象训练结束时 mAP50 高达 0.95部署到真实摄像头后精度跌到 0.6。训练日志和推理结果之间差异非常大且重训两次都是同样表现。原因数据集在采集时没有严格按时间序列切分。同一个垃圾箱在不同角度拍的照片一部分被放进 train另一部分被放进 val。因为背景、光线、摆放位置几乎一致模型在验证集上相当于“开卷考试”mAP 虚高几个点甚至十几个点都很正常。这不是代码 bug是数据划分策略问题。解决必须按文件列表做一次查重。最直接的方式是检查原始文件名采集时如果文件名中带序号或时间戳按序列的前 80% 训练、后 20% 验证重新切分。文件名没有规律时用感知哈希做图像去重import imagehash from PIL import Image from pathlib import Path hashes {} for p in Path(garbage4/images).rglob(*.jpg): h imagehash.phash(Image.open(p), hash_size16) for existing, path in hashes.items(): if h - existing 6: print(f重复样本: {path} 与 {p}) break else: hashes[h] p两个图像的感知哈希汉明距离小于 6可以判定为同一场景的不同采样需要人工确认后从训练集或验证集中剔除。数据集采集中如果连续拍摄同一个垃圾对象会大量出现这类问题。划分数据集的正确做法是按拍摄时间或拍摄地点分桶而不是打乱全部图片后随机切分随机切分在存在连续采集样本时极易造成数据泄露你无法控制同一垃圾桶在相邻几帧出现的边界。4.4 坑四归一化坐标出现小于 0 或大于 1 的越界框现象训练正常启动没有报错但某个类别 AP 特别低可视化预测时发现模型输出的框一部分在图片边缘外。原因标注框在标注工具里被拖出了图片边线或者经过自动标注算法后处理时没有裁切。YOLO 的归一化坐标允许数值大于 1模型会努力把边界外的内容也卷进来框的位置信息被污染。解决训练前扫描全部标签文件找所有坐标越界的框from pathlib import Path bad [] for p in Path(garbage4/labels).rglob(*.txt): for i, line in enumerate(p.read_text().splitlines()): vals line.split() if len(vals) ! 5: bad.append((p, i 1, 字段数 ! 5)) continue _, x, y, w, h [float(v) for v in vals] if not (0 x 1 and 0 y 1 and 0 w 1 and 0 h 1): bad.append((p, i 1, line.strip())) print(f越界或非法框数量: {len(bad)}) for file, line_no, content in bad[:20]: print(f {file} line {line_no}: {content})批量修正时把坐标 clamp 到 0.0001~0.9999 区间即可。但严重超出边界的框比如 x_center 1.5直接 clamp 会得到意义不明的窄条框这类数据建议从训练集中剔除而不是修坐标。边界框造成的问题不只是个别类别 AP 低还可能让 NMS 在推理阶段产生大量冗余框因为模型学会了预测那些超出图像范围的候选区域。4.5 坑五同一目标在数据集中出现几十次重复样本抬高水指标现象mAP50 看上去很高但训练 loss 下降速度异常快前 10 个 epoch 就到 0.1 以下推理时对新场景泛化很差。原因很多垃圾图像采集来自视频抽帧同一个瓶子在连续 50 帧中出现抽帧间隔不够时这些几乎相同的图片被同时放进数据集。训练集和验证集中存在大量近重复样本模型实际学到的有效样本远小于文件数量。这类问题不容易通过文件名判断。解决训练前做一次感知哈希去重第 4.3 节中的脚本同样适用于训练集内部去重。如果发现一组图片相似度极高保留一张或最多两张删除其余。视频抽帧采集时要保证间隔至少 1 秒以上并规避目标静止不动的连续帧。图像相似度阈值可以调整hash_size 设 16 时阈值 6 是比较严格的去重只是约束训练集内部重复时可以放松到 10会保留同场景的视角变化。5. 训练完成后的验证动作混淆矩阵、可视化检查和部署前的一个细节训练结束不意味着模型真正可用四分类任务在真实场景中的表现需要三个动作确认混淆矩阵看类别间纠缠、可视化预测找标注盲区、导出模型时确认 names 没有随模型丢失。一套流程走完才具备落地条件。5.1 一次验证命令三个必须看的输出文件yolo val modelruns/train_garbage4/baseline_v1/weights/best.pt \ datagarbage4.yaml验证完成后重点看三个文件confusion_matrix.png、val_batch1_pred.jpg、results.csv。混淆矩阵看出哪些类别之间持续混淆四分类任务中最常见的是其他垃圾和厨余垃圾互相误判原因是外卖盒里面残留剩饭标注时不同标注员对类别归属的理解不一致。可视化预测图片则能定位漏标注区域问题。如果混淆矩阵里 diagonal 在 0.9 以上但实际场景表现差回到第 4.3 节查数据泄露。5.2 导出 ONNXnames 与元信息必须一起带走部署到边缘盒子或 ARM 板时通常需要导出成 ONNXyolo export modelruns/train_garbage4/baseline_v1/weights/best.pt \ formatonnx imgsz640ONNX 文件本身不包含类别名称的强约束很多推理框架会把输出张量的最后一维直接映射成类别编号。导出后写推理代码时第一件事就是从原项目的 data.yaml 中把 names 列表复制到部署代码里并核对顺序。之前某项目在部署阶段就遇到过这个问题模型训练正常推理代码里 categories 写成了[other, recyclable, kitchen_waste, hazardous]结果全部预测类别整体旋转一位排查了三天最后发现是列表顺序与 yaml 不一致而不是模型问题。从那以后我每次训练结束都强制走一遍类别统计、同名校验、验证集混淆矩阵三个动作再把 names 列表原样贴进部署代码里做一遍逐项对比确认四类的顺序与 yaml 完全一致后才允许发布模型。这套流程多花十分钟但比训练完直接部署然后在线下返工要省心得多。希望帮到你。本文还有配套的精品资源点击获取