ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

基于YOLOv8的垃圾分类识别:注意力机制与小目标检测改进实践

基于YOLOv8的垃圾分类识别:注意力机制与小目标检测改进实践 1. 项目概述为什么垃圾分类识别要选中目标检测这条路先把话说在前面垃圾分类这件事看着简单真正落地到实际场景里就知道有多“折磨人”。很多小区和垃圾处理厂的现状是靠人工巡检、靠摄像头人工盯屏分错率高不说效率也撑不起来。我刚开始接触这个课题的时候最直接的感受就是这不是一个单纯的图像分类问题而是要在复杂背景下、多目标堆叠场景里同时告诉系统“这是什么垃圾”以及“它在哪里”。这正是目标检测的典型应用场景。而之所以最终选择YOLOv8作为基线模型去做改进原因也很直白深度学习图像识别目前真正能扛住工程化落地的目标检测方案YOLO系列是最稳的一档。它属于单阶段检测器速度与精度兼顾不像两阶段检测器那样先提候选框再做二次分类部署起来麻烦也不像SSD那样对中小目标的特征融合能力偏弱。YOLOv8相比YOLOv5又做了几处关键升级比如C2f模块替换C3模块、Anchor-Free的检测头结构、解耦分类与回归分支这些改动让模型收敛更快、训练更稳定、小目标检出率也更好一些。这篇文章适合几类人准备做相关毕业设计或者课程项目的学生正在评估垃圾分类识别系统可行性的一线工程师以及所有想在YOLOv8基础之上做“有效改进”而不是“花式堆模块”的学习者。我会把从数据集构建、基线模型分析、改进思路、训练调参到最终评估部署的完整过程拆开讲重点讲“为什么这么做”和“这么做踩了什么坑”。2. 数据攻坚战垃圾分类数据集没那么好伺候2.1 类别设计怎么定才是最核心的问题垃圾分类识别和通用目标检测最大的不同是类别定义本身带有强烈的地域和管理属性。不同城市对垃圾类别的划分不完全一样有的分四类有的分五类还有按可回收物再细化到塑料、纸类、玻璃、金属的。我踩过的坑是一开始直接照搬公开数据集的40多类标签去训练结果模型在真实场景里显得“过度聪明”——它能把一张纸团识别成“纸板”却不能在“可回收”这个大背景下正确决策。所以我在实际项目中重新设计了类别体系按“最终处理路径”来分原则就是落地时分类越少越稳。最终锁定为六类可回收物、厨余垃圾、有害垃圾、其他垃圾外加“瓶类”和“纸质品”两个高风险细分类别。原因也很实际这两类在可回收物里占比最高、外形差异大单靠混在一起训练容易互相干扰拆出来单独监督效果更稳。如果说你的场景是小区垃圾桶前端识别建议控制在6到10类之间如果是做课题演示用TrashNet这类公开数据集也可以。但要注意公开数据集背景干净、单目标居多和真实场景差距明显最好是“公开集预训练 自建数据微调”的组合打法。2.2 数据采集、标注与增强的实操细节数据数量上我的经验是每类至少500到1000张目标实例总数不低于10000个。垃圾分类识别里真正难的不是数量而是多样性——同样一个矿泉水瓶透明瓶、绿瓶、压扁的瓶、带标签的瓶、反光的瓶看起来是同一个类别模型的感受完全不同。采集时要覆盖不同光线、不同角度、不同距离、遮挡程度、垃圾桶内堆叠状态等。标注工具我用的是LabelImg标准格式是PASCAL VOC的XMLYOLO训练需要用txt格式的归一化坐标ultralytics仓库自带转换脚本也可以直接用labelImg的YOLO模式输出。这里有几个容易翻车的地方类别名称必须在标注前定死训练时读的是索引编号名称不一致会导致标签错乱。遮挡严重的物体只要可见面积超过三分之一我会选择标注被大面积遮挡、肉眼都难分辨的直接删掉。模糊到连人眼都看不出类别的图片果断清洗掉不然模型会把“模糊感”本身当特征。数据增强不要盲目开满。YOLOv8训练时默认启用Mosaic和MixUp这在通用场景没问题但垃圾分类场景里有些物体对旋转很敏感——比如一个立着的饮料瓶旋转180度以后变成“横躺的瓶子”这仍然合理但一袋打开的厨余垃圾翻过来之后视觉语义会变得很奇怪。所以我关闭了180度强旋转保留小角度旋转、平移、缩放、HSV色彩变换和Mosaic并把MixUp概率调低到0.1左右。增强的目的并不是简单增加数据量而是让模型对真实环境中的光照、尺度、遮挡更鲁棒一旦破坏语义就适得其反。数据集划分也要讲策略。我按“视频/拍摄批次”为单位划分训练集、验证集、测试集比例控制在811而不是把所有图片随机打乱再划分。因为同一批拍摄的序列帧之间非常相似随机划分会导致验证集和训练集高度重叠mAP虚高一到真实场景就露馅。3. 改进方案的设计与实现让YOLOv8更懂生活垃圾3.1 基线模型为什么选YOLOv8的这几个模块先花点时间过一遍YOLOv8的结构这样才能理解后面改的是什么。以YOLOv8s为例骨干网络用C2f模块堆叠出多尺度特征配合SPPF做池化金字塔颈部是PAN-FPN结构把深层语义信息和浅层细节信息双向融合检测头则是解耦头分类和回归各走一支。整个过程没有Anchor预置框直接在每个位置预测目标框和类别减少了很多后处理复杂度。相对于Faster R-CNN、SSD和YOLOv5YOLOv8的优势可以列成这样模型检测速度小目标能力训练友好度部署生态Faster R-CNN慢较好较低需调参一般SSD快弱一般特征融合浅一般YOLOv5快中上好成熟YOLOv8很快较好高配置简单非常好实际上YOLOv8最大的优势还不是指标高而是整个训练、验证、导出、部署流程被ultralytics封装得极其顺滑对做课题研究和工程落地都友好。但基线再好直接拿来识别生活垃圾还是有两个问题一是一些小目标比如烟蒂、瓶盖、纸团特征少、容易被下采样丢掉二是垃圾类之间外观相似度高例如透明塑料袋和白色餐盒碎片模型容易混淆。这两个问题就是我们改进的主攻方向。3.2 改进一在检测颈中加入EMA注意力模块强化关键特征第一个改进是对抗相似类别混淆。YOLOv8默认的C2f模块可以高效提取特征但它不会主动告诉网络“哪些通道更重要”。我选择在颈部关键位置嵌入EMA注意力机制模块替换部分C2f结构而不是一股脑把注意力加在骨干每一层。EMA模块相比SE、CBAM在保留跨通道信息交互的同时还引入了一部分空间注意力权重对小目标特征更加友好并且参数增量很小适合边缘设备部署。这里有个决策思路注意力模块的本质是让网络更关注信息量大的区域但加在底层骨干上容易在早期训练阶段破坏特征提取稳定性反而拖慢收敛。我最终只在PAN-FPN的自顶向下路径两处做了替换也就是融合层的关键节点。实验对比下来加了EMA之后纸团、塑料袋这类容易误判的类别精确率提升了约3到5个点推理速度几乎无损耗。写进YOLOv8结构里并不难需要改的东西分两块。第一块是拿到EMA模块的定义代码把模块注册到ultralytics的模型仓库里第二块是在模型的yaml文件中用自定义C2f_EMA替代对应位置的C2f。只要把模块类和yaml配置对应上训练器就能自动加载。需要特别注意模块的输入输出通道数要和原位置保持完全一致否则会直接报维度错误。3.3 改进二增加P2检测层提升小目标召回率垃圾分类场景里最难检的不是瓶子不是纸箱而是烟蒂、瓶盖、牙签这类小尺寸物体。YOLOv8默认从P3开始输出检测层特征图尺寸是输入图像的1/8对特别小的目标来说几层下采样之后特征已经不明显了。为了提升小目标召回我在检测头部分增加了一个P2输出层也就是让模型从骨干的浅层特征图1/4尺寸直接接出一个检测分支。这样相当于给检测头多提供了一份更高分辨率的特征图保留了更多小目标的细节位置信息。代价是计算量会小幅增加特征融合结构也会更复杂一些我会配合修改后续的颈部特征图数量。这个改进我在yaml里通过调整backbone输出节点和增加一个检测头来完成。有一个很直观的现象增加P2层之后训练前期mAP上升比以前慢因为浅层特征语义信息偏少刚开始学起来吃力但训练充分之后小目标的召回率提升非常明显mAP50-95的涨幅比mAP50还要明显。这里给一个建议如果设备算力紧张可以直接在标准检测层上把输入分辨率从640提升到768简单粗暴也能改善小目标但长期来看P2层的收益更可持续因为它解决的是结构性问题升分辨率只是缓解症状。3.4 改进三用Wise-IoU损失改善低质量样本的梯度贡献第三个改进在损失函数层面。YOLOv8默认使用CIoU作为回归损失CIoU考虑了重叠面积、中心点距离和宽高比整体表现均衡。但在垃圾堆叠场景里很多目标天然存在遮挡和截断边界框本身就是模糊的这时候CIoU会持续给这些“低质量样本”施加不合理的惩罚梯度迫着模型去拟合那些标注本身就不确定的位置。我换成了Wise-IoU v3。它最核心的思想是给不同质量的样本动态分配梯度权重高质量、低IoU的样本获得更多学习权重而过高IoU的易分类样本则被降权避免模型在简单样本上空转。这个改进不需要改变模型结构只替换损失函数实现属于性价比极高的改动。替换后的训练过程有一个明显感觉前期的loss下降不如CIoU“好看”因为Wise-IoU刻意弱化了一部分极端样本的影响。但从验证集的表现来看框的定位精度更准了尤其是遮挡目标的边界框输出稳定很多。训练到后期的mAP50-95比基线模型高出2个点左右这在小数据集上已经算很可观的收益。4. 实操过程训练、评估与调参全流程4.1 环境准备从硬件选择到环境配置做深度学习项目硬件是第一道门槛。我用的是单张RTX 3060 12G显存跑YOLOv8s级别的模型完全没问题YOLOv8l需要缩小batch size也能跑。如果只有GTX 1660Ti这种6G显存的卡建议用YOLOv8n或YOLOv8s配合混合精度训练把输入分辨率控制在640batch size设为8到16之间。软件方面我用的是PyTorch 2.1 CUDA 11.8 Python 3.10。安装直接走ultralytics官方pip包即可它会自动带好大部分依赖pip install ultralytics装完以后可以检查一下是否支持GPU训练python -c import torch; print(torch.cuda.is_available())如果输出False多半是PyTorch版本和CUDA驱动不匹配。我建议直接从PyTorch官网的desktop页面按当前CUDA版本号选择对应的安装命令不要图省事装CPU版本。数据集方面别自己手工去写加载器把图片和标签按官方目录结构放好就行dataset/ ├── images/ │ ├── train/ │ └── val/ └── labels/ ├── train/ └── val/然后写一个data.yaml指定路径、类别名和类别数path: D:/garbage_dataset train: images/train val: images/val nc: 6 names: [recyclable, kitchen, harmful, other, bottle, paper]有两点容易忽略路径建议用绝对路径避免IDE工作目录不同导致路径解析错误中文类别名虽然能训练但后续导出部署时不少推理框架对中文支持不好建议统一用英文标签最后再做一层中文映射。4.2 训练参数怎么定一次说清epochs、batch、lr那些事训练命令里参数很多我逐个说清楚它是什么含义、应该怎么选。先放一条完整的参考命令yolo train datagarbage.yaml modelyolov8s.pt epochs300 imgsz640 batch16 device0 optimizerAdamW lr00.001 weight_decay0.0005 patience50 augmenttrue close_mosaic10epochs训练轮数。垃圾分类这种中小规模数据集我建议300起步配合早停机制。你不需要真跑到300验证集指标如果连续patience轮没有提升训练会自动停。imgsz输入分辨率。640是性价比很高的默认值目标偏小的时候可以尝试768显存充足甚至可以上1024。batch单卡批次大小。显存不够的首先砍batch配合梯度累积效果也不会差太多。我这里设16是基于12G显存YOLOv8s加上大部分增强比较稳。optimizer优化器。YOLOv8默认是SGD稳定但收敛慢。我实测AdamW在前期收敛更快后期精度也不吃亏尤其配合Wise-IoU这类损失函数整体训练曲线更平滑。lr0初始学习率。AdamW下1e-3比较合理SGD可以到1e-2。学习率是全局最敏感的参数如果发现loss发散或者震荡剧烈第一时间降到原来的五分之一再试。close_mosaic最后10轮关闭Mosaic增强。这个细节很重要。Mosaic增强虽然能大幅提升样本多样性但它合成的图像和真实场景差距大训练最后阶段关闭它让模型回到真实分布上微调能小幅提升最终精度。训练过程中我习惯记录几个关键信号。第一个是训练集loss下降速度如果10轮内train/box_loss没有显著下降说明学习率太低或者数据集有问题第二个是验证集mAP曲线的上升趋势mAP50和mAP50-95之间的差距如果非常大说明模型定位精度一般、和分类精度的差距太大第三个是是否过拟合具体看训练loss持续下降、验证loss反而上升。4.3 训练曲线怎么看判断模型健康度的三个指标很多新手在训练结束后只关注最终的mAP数值却忽略了训练过程中的曲线形态。我分享几个判断经验train/box_loss代表预测框回归损失正常情况下应该稳步下降并在后期趋于平台。如果出现突然反弹通常是学习率过大或数据里混入了异常标注建议可视化检查该批次图片。metrics/mAP50是IoU阈值0.5时的平均精度反映的是“框大概框对”的能力metrics/mAP50-95则要求在更严格的IoU阈值下也准确反映定位精度和框质量。垃圾分类场景里如果mAP50能到90%以上但mAP50-95只有50%出头说明框的位置不精细这个在遮挡堆叠场景里非常常见。一个实用技巧早停确实能省时间但不要完全依赖它。我会先关掉早停跑完前50轮通过验证集指标的波动幅度估算数据集的质量和难度。数据越难指标波动越大早停的patience参数就要设高一些否则模型还没收敛就被停了。4.4 评估与部署从混淆矩阵到边缘设备推理验证完成后ultralytics会自动产出很多评估结果我最常看的是confusion_matrix.png和results.png。混淆矩阵一定要逐类别看它能直接暴露哪两类垃圾经常互相误判。我遇到过的问题就是“其他垃圾”和“可回收物”之间的混淆天气反光的时候尤其严重。后来发现是训练数据里这两类中都有大量塑料袋单纯靠视觉特征本来就很难区分后面在数据层面单独增加了“干净透亮塑料袋”和“脏污暗沉塑料袋”两组对比样本才算缓解。评估指标的真正意义在于指导数据迭代而不是自我感动。第一次训练mAP50到了82%看似不错但一看混淆矩阵玻璃瓶的召回率只有61%等于三瓶里就有一瓶漏检。针对这个类别补数据、加增强再训练了一个版本才把召回率拉回80%以上。部署阶段我把训练好的模型导出为ONNXyolo export modelbest.pt formatonnx opset12在边缘设备上我用rk3588做过部署需要先转成RKNN格式量化用int8YOLOv8n级别可以跑在30ms左右基本满足实时检测需求。如果是普通的x86服务器直接跑PyTorch模型或ONNX Runtime都行吞吐量更大。NMS后处理参数也要根据场景调。默认conf_thres0.25和iou_thres0.45在真实场景下容易出现重复框或者漏检小目标。我建议在验证集上做一组小实验把conf_thres在0.1到0.5之间扫一遍观察mAP和单帧耗时曲线选择一个让你部署场景“误检不爆炸、漏检也能接受”的平衡点。垃圾分类应用里漏检送错垃圾的代价远高于多框一次所以我的阈值会故意压低一些。5. 常见问题与排查实录5.1 训练不收敛、loss爆炸、显存不足我自己训练过程中遇到最多的问题基本都能整理成下表现象常见原因解决方案loss输出为NaN学习率过大、梯度爆炸降低lr0到原来的1/5开启梯度裁剪显存OOMbatch过大、分辨率过高降低batch size使用梯度累积开启AMP混合精度训练集loss下降验证mAP不涨过拟合或数据划分泄露增加数据量、加强增强、检查训练验证集是否重叠mAP50和mAP50-95差距过大定位框不够精确增加训练轮数、使用Wise-IoU/CIoU、提高输入分辨率某类别召回率明显偏低样本数量少或背景复杂针对该类别补充数据、做特定类别的过采样增强有一个案例值得单独拿出来说我第一次换用AdamW优化器时训练了10轮loss都很正常然后突然开始震荡。排查后发现是因为weight_decay设置不对。AdamW对权重衰减的处理方式和SGD不同SGD下常用的0.0005在AdamW里偏大导致权重波动太剧烈。改成0.0001之后曲线马上就正常了。5.2 目标检测模型对生活垃圾场景的易错点垃圾分类识别里有些错误带有很强的领域特征这里单独展开说。第一类是透明物体问题。透明塑料瓶、玻璃瓶在自然光下几乎没有稳定的颜色特征只有边缘和透视形变。模型容易把它们和背景混在一起。解决思路不只是加数据还可以在预处理阶段加强边缘增强或使用HSV空间变换增强让模型更关注形状信息而不是颜色纹理。第二类是相似材质混淆。外表看起来都“皱巴巴、灰蒙蒙”的脏餐巾纸、纸盒碎片、塑料袋残片视觉特征高度接近。出现这种误判时不要急着调结构先回到数据集里统计一下每类图片的“整体色调分布”如果本来就是同色系再怎么调模型也难。可以考虑临时增加“颜色先验”后处理规则比如把极大概率落在“其他垃圾”且颜色特征高度符合的样本强制归类到指定类别。第三类是极端长宽比目标。筷子、吸管、长绳这类细长物体在常规数据增强中很容易被标注框拉变形导致回归精度差。我建议在预处理部分对长宽比大于31的目标单独做“等比缩放裁剪”处理而不是简单缩放到固定尺寸。5.3 改进模块“加上就掉点”的排查思路这是很多做YOLOv8改进的同学最头疼的情况注意力模块加了mAP反而降了。这个情况我遇到过不止一次排查顺序一般是这样的先看训练曲线。如果加模块之后训练loss降得更慢说明模块引入了额外的优化难度。很多注意力模块内部有额外的激活函数和权重初始化不当会干扰原有特征流的传播。这时候可以通过在模块后面加一个残差连接来缓解至少保证模块在最差情况下也就是退化成恒等映射不会对原有特征造成破坏。再看学习和数据量是否匹配。一些小数据集上堆模块的收益并不明显因为模型容量提升了但数据量不够最后表现的方差会很大。如果你在一个1800张图片的小数据集上加了三个模块然后掉点了大概率不是模块不行而是数据集配不上模型容量。最后检查是否加错位置。有些注意力机制加在检测头前面效果很好加在骨干底层反而是负优化。我们组里现在的新项目修改模块之前一定会先在同一个数据集、同样的训练配置下跑三次基线取方差再对比改进后的结果。没有方差意识很多结论都是噪音。6. 一点个人的实际体会整个项目做下来我最大的体会是目标检测项目的成败不只在模型结构和训练技巧而在你对数据和场景的理解深度。垃圾分类这个题目看起来很“标准化”但落到小区、垃圾中转站、环卫车等不同场景光照、视角、遮挡程度完全不同。模型改进能带来的精度提升通常在小几个点但一次高质量的数据补充、一个合理的类别体系设计带来的提升往往是大几个点甚至翻倍。还有一点就是改进要克制。YOLOv8已经是很成熟的基线了把EMA、P2检测层、Wise-IoU这些改进真正理解清楚比把十几个模块全堆上去要靠谱得多。我最后交付的版本单张RTX 3060训练约8小时验证集mAP50-95在63%左右在树莓派级别设备上也能跑实时推理。你不需要追求论文里那种高不可攀的指标先把“在真实场景下稳定工作”这件事做扎实就已经超过了大多数演示级项目。如果你的后续方向是想往论文或竞赛走建议在数据层面再挖一挖引入半监督标注、利用视觉大模型辅助标注、做基于CLIP的开放词汇垃圾识别等。如果目标是落地产品那下一步的重心应该放在推理优化和后处理规则上边缘设备上的量化、剪枝、模型蒸馏每一项都比继续堆注意力模块更实用。
RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进