☰
YOLO垃圾四分类数据集训练前必查的细节与避坑指南
2026/10/12 1:49:38 网站建设 项目流程

简介: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~3
x_center框中心点横坐标 / 图片宽0~1
y_center框中心点纵坐标 / 图片高0~1
width框宽度 / 图片宽0~1
height框高度 / 图片高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(f"class {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: other

path建议写绝对路径。YOLOv8 的path是相对当前工作目录解析的,如果在项目根目录下执行命令,相对路径要写成./garbage4,换一台机器就要改一次。写绝对路径可以避免这类环境迁移问题,但代价是代码库换个仓库路径就要同步改配置。train和val是相对于path的子路径,不要加上/home/dev/前缀。names的字典顺序没有作用,真正起作用的是键名 0~3,它必须和 txt 文件里的第一个字段一致。如果标注里1代表可回收物,而 yaml 里1是厨余垃圾,训练不会报任何错误,推理结果则会整体错位。检测场景中类名建议用英文小写加下划线,中文类名也能用,但导出 ONNX 后在部分推理框架里会出现编码乱码。

3.2 训练命令:从 YOLOv8s 起步,backbone 尺寸不要一上来就选大的

四分类垃圾目标不算小,类别间外形差异也明显,s 级模型在这个任务上是性价比最高的起点。直接从 x 级模型开始练,训练时间拉长,验证精度的提升往往不超过两个点,但部署体积翻了几倍。

yolo train model=yolov8s.pt \ data=garbage4.yaml \ epochs=200 imgsz=640 batch=16 \ patience=50 \ project=runs/train_garbage4 \ name=baseline_v1

各参数的选择逻辑如下表:

参数起步值调整方向
modelyolov8s.pt精度不够再上 m,显存紧张用 n
epochs200小数据集 100 足够,大数据集 300
imgsz640目标普遍偏小再上 960
batch168G 显存降到 8,加梯度累积到等效 16
patience50数据集大、epochs 多时可以放宽到 80

patience=50是关键参数,表示验证集指标连续 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,模型训练时 class=4 虽然没有在 yaml 中被定义,但数据集内部类别定义和模型输出层之间发生了整体偏移。YOLO 训练不会对 class 编号做合法性校验,没有显式定义 class>=nc 的检查逻辑,因此这种错误会全程静默。

解决:在训练前增加一步强制校验,扫全部 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_size=16) 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 model=runs/train_garbage4/baseline_v1/weights/best.pt \ data=garbage4.yaml

验证完成后重点看三个文件:confusion_matrix.png、val_batch1_pred.jpg、results.csv。混淆矩阵看出哪些类别之间持续混淆,四分类任务中最常见的是其他垃圾和厨余垃圾互相误判,原因是外卖盒里面残留剩饭,标注时不同标注员对类别归属的理解不一致。可视化预测图片则能定位漏标注区域问题。如果混淆矩阵里 diagonal 在 0.9 以上,但实际场景表现差,回到第 4.3 节查数据泄露。

5.2 导出 ONNX:names 与元信息必须一起带走

部署到边缘盒子或 ARM 板时,通常需要导出成 ONNX:

yolo export model=runs/train_garbage4/baseline_v1/weights/best.pt \ format=onnx imgsz=640

ONNX 文件本身不包含类别名称的强约束,很多推理框架会把输出张量的最后一维直接映射成类别编号。导出后写推理代码时,第一件事就是从原项目的 data.yaml 中把 names 列表复制到部署代码里,并核对顺序。之前某项目在部署阶段就遇到过这个问题:模型训练正常,推理代码里 categories 写成了["other", "recyclable", "kitchen_waste", "hazardous"],结果全部预测类别整体旋转一位,排查了三天,最后发现是列表顺序与 yaml 不一致,而不是模型问题。从那以后我每次训练结束,都强制走一遍类别统计、同名校验、验证集混淆矩阵三个动作,再把 names 列表原样贴进部署代码里做一遍逐项对比,确认四类的顺序与 yaml 完全一致后才允许发布模型。这套流程多花十分钟,但比训练完直接部署然后在线下返工要省心得多。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询