
1. 从一张生活照到可回收物这个项目到底在做什么垃圾分类这件事说起来简单做起来是真磨人。我住的小区从去年开始搞定时定点投放每天早上七点到九点、晚上六点到八点两个时间段各摆四个桶旁边还站着一位志愿者阿姨。头一个月我几乎每天都在“这是干垃圾还是湿垃圾”的纠结里度过外卖盒要洗干净晾干再扔用过的纸巾不管多湿都是干垃圾大骨头算其他垃圾而鸡骨头算厨余——这套规则背下来比背单词还费劲。后来我就想能不能让机器替人做这个判断拍一张照片模型告诉我这玩意儿该进哪个桶。这就是基于深度学习的垃圾分类识别目标检测系统最朴素的出发点。它不是要取代人的判断而是把“识别”这一步自动化降低普通人参与垃圾分类的认知门槛。这个项目的核心任务用一句话概括输入一张包含生活垃圾的图像输出图中每个垃圾实例的类别标签和位置框。类别通常按四分类走——可回收物、厨余垃圾、有害垃圾、其他垃圾有些实现会细分到几十个小类比如塑料瓶、纸箱、电池、灯管、果皮、烟头等等。位置框用矩形表示格式一般是[x_min, y_min, x_max, y_max]或者中心点加宽高的形式。为什么选目标检测而不是单纯的图像分类这是很多人一开始会走弯路的地方。图像分类只回答“这张图里是什么”它假设整张图只有一个主体。但生活垃圾的场景天然是多目标、密集、遮挡、尺度差异大的一个垃圾桶里可能同时有塑料瓶、纸团、果皮、包装袋它们互相叠压大小从几厘米到几十厘米不等。分类模型面对这种图会直接懵掉因为它没法告诉你“左上角那个是瓶子右下角那个是纸团”。目标检测则天然处理这种“一张图多个物体、每个物体都要定位”的需求这也是这个项目必须用检测框架的根本原因。那为什么是YOLOv8YOLO 系列从 v1 到 v8主线一直是“在保证实时性的前提下把精度往上推”。垃圾分类识别如果要落地到实际场景——比如智能垃圾桶的摄像头、手机 App 的实时识别、边缘设备上的本地推理——推理速度是硬指标。你不可能让用户拍完照等三秒钟才出结果。YOLOv8 在 COCO 上的表现已经证明它能在中端 GPU 甚至一些边缘芯片上跑到实时同时它的工程化程度很高Ultralytics 官方把训练、验证、推理、导出全流程封装得相当顺手配置文件清晰改起来不痛苦。对于一个以“识别垃圾”为目标的工程项目来说选一个成熟、社区活跃、文档齐全的检测框架比自己去搭一个花哨但没人维护的网络要务实得多。这个项目适合谁参考我把它分成三类人。第一类是深度学习入门者想找一个有真实意义、数据可获取、流程完整的项目练手垃圾分类正好满足——公开数据集有标注格式标准评价指标明确。第二类是做嵌入式或边缘部署的工程师想把检测模型塞进 RK3588、Jetson 或者带摄像头的 MCU 方案里垃圾分类是一个很好的验证场景。第三类是参加竞赛或做毕业设计的学生这个题目既有技术深度改进算法、调参、对比实验又有应用价值环保、智慧城市写出来的东西不空。我后面会按“整体设计思路 → 核心细节与实操要点 → 完整实操流程 → 常见问题排查”这条线展开把我在这个方向上踩过的坑、调过的参数、试过的改进点都摊开讲。你不需要有很深的深度学习背景但至少要能看懂 Python知道什么是张量、什么是损失函数剩下的我们边做边补。2. 整体设计与技术选型为什么这么搭2.1 检测框架的选型逻辑YOLOv8 赢在哪里目标检测的算法家族大致分两派两阶段检测器以 Faster R-CNN 为代表和单阶段检测器以 YOLO、SSD、RetinaNet 为代表。两阶段的做法是先由 RPN区域提议网络生成一堆候选框再对每个候选框做分类和回归精度通常更高但速度慢单阶段则是直接在特征图上预测类别和框一步到位速度快。垃圾分类这个场景我的判断是速度优先、精度够用即可。原因很实际用户拍一张照片期望的是“秒出结果”而不是等模型慢慢精修。而且垃圾类别的区分度其实不低——塑料瓶和果皮在纹理、颜色、形状上差异明显不像细粒度分类那样需要极强的特征提取能力。所以单阶段检测器是更合理的选择。在单阶段里YOLOv8 相比前代和同期竞品的优势我总结成三点Anchor-Free 设计。YOLOv3/v5 用的是 anchor-based需要预先聚类出一组先验框尺寸anchor 的设置对结果影响很大调起来烦。YOLOv8 改成了 anchor-free直接预测目标中心点和宽高少了一堆超参对小目标和形状差异大的垃圾更友好。C2f 模块与更深的特征融合。YOLOv8 的 backbone 用了 C2fCSP 结构的改进版在保持轻量的同时增强了梯度流动neck 部分用 PAN-FPN 做多尺度特征融合这对垃圾这种尺度跨度极大的目标很关键——一个烟头和一张报纸在同一张图里没有多尺度融合根本抓不住。工程化与生态。Ultralytics 的ultralytics包把训练、验证、预测、导出ONNX、TensorRT、OpenVINO 等全串起来了一行命令就能跑。社区里关于 YOLOv8 的改进方案、注意力机制插入、损失函数替换的讨论非常多你想改哪里基本都能找到参考。当然选 YOLOv8 不代表它完美。它在极小目标和严重遮挡场景下仍然会漏检这也是为什么标题里强调“改进算法”——后面我会专门讲几个实用的改进方向。2.2 数据集的设计与来源垃圾数据从哪来没有数据再好的模型也是空壳。垃圾分类检测的数据集来源无非三条路公开数据集、自采集、合成增强。公开数据集里比较常用的是TrashNet主要是分类不是检测、TACOTrash Annotations in Context带检测标注类别偏细、以及一些竞赛平台上的垃圾分类检测数据集。TACO 的问题是类别太细、长尾严重直接拿来训四分类需要做标签映射。我实际用下来更推荐的做法是以公开数据集为底自己补拍一部分真实场景图。为什么必须自己补拍因为公开数据集大多是在干净背景下拍的单个物体而真实场景是垃圾桶里一堆东西叠在一起、光照不均、有反光、有遮挡。模型在干净数据上训出来一到真实场景就崩。我自己的做法是拿手机在小区垃圾桶旁边蹲了三个傍晚拍了大概 800 张真实投放场景图涵盖白天、傍晚、阴天三种光照然后手工标注。这 800 张带来的精度提升比在公开数据集上多加 2000 张干净图还明显。标注工具用LabelImg或者Roboflow都行。LabelImg 是本地工具离线可用适合数据敏感的场景Roboflow 在线标注、增强、导出一条龙团队协作方便。标注格式统一用YOLO 格式每张图对应一个.txt每行是类别id 中心x 中心y 宽 高坐标都归一化到 0~1。这个格式 YOLOv8 直接吃不用转换。类别设计上我建议先做四分类再考虑细分。四分类是可回收物0、厨余垃圾1、有害垃圾2、其他垃圾3。如果一上来就做几十类标注成本爆炸而且类间边界模糊比如“污染过的纸”到底算可回收还是其他模型学起来也痛苦。四分类跑通之后再在可回收物下面细分塑料、纸类、金属、玻璃这样迭代更稳。2.3 改进方向的取舍改哪里最划算“基于 YOLOv8 改进算法”这句话落到实操上有很多种改法。我按性价比排个序从高到低改进方向具体做法预期收益实现难度注意力机制在 backbone 或 neck 插入 CBAM、SE、CoordAtt中高对小目标和遮挡有效低损失函数替换用 WIoU、EIoU 替换 CIoU中回归更准低数据增强策略Mosaic、MixUp、Copy-Paste 小目标高尤其对小目标低Head 改进解耦头、增加小目标检测层中高中Backbone 替换换 MobileNet、GhostNet 轻量化速度提升精度略降中知识蒸馏大模型教小模型高但流程复杂高我的建议是先把数据增强和注意力机制做扎实这两块投入产出比最高。损失函数替换属于锦上添花等基础跑通了再试。Head 改进和 Backbone 替换要看你的部署目标——如果是要上 RK3588 这种边缘芯片轻量化 backbone 是必须的如果只是服务器端跑没必要牺牲精度。这里特别说一下协调注意力机制CoordAtt它在垃圾分类场景里效果不错。普通注意力只关注通道或空间一个维度CoordAtt 把位置信息编码进通道注意力里相当于告诉模型“这个特征在图的哪个位置”。垃圾检测里物体的位置分布其实有规律——瓶子通常立着、纸团通常成团、果皮形状不规则位置感知能帮模型区分这些模式。3. 核心细节与实操要点把每个环节拆开看3.1 环境配置别在第一步卡住YOLOv8 的环境配置说简单也简单说坑也多。我按“最稳路径”给你捋一遍。首先是Python 版本。Ultralytics 官方推荐 3.8 到 3.11我实测 3.10 最稳。3.12 有些依赖还没跟上容易出幺蛾子。用 conda 建一个独立环境别在 base 里瞎装conda create -n yolo_garbage python3.10 conda activate yolo_garbage然后是PyTorch。这一步最容易出错因为要匹配 CUDA 版本。先查你的显卡驱动支持的最高 CUDA 版本nvidia-smi右上角会显示CUDA Version: 12.x之类的。注意这是驱动支持的最高版本不是你必须装的版本。去 PyTorch 官网找对应命令比如 CUDA 11.8 的pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118装完验证一下import torch print(torch.__version__) print(torch.cuda.is_available())如果cuda.is_available()返回 False别急着往下走先把这步解决。常见原因是装了 CPU 版、CUDA 版本不匹配、或者驱动太旧。最后装 ultralyticspip install ultralytics注意不要同时用 pip 和 conda 装同一个包混着装容易出现版本冲突。我一般统一用 pip。如果你用的是GTX 1660 Ti这类 6GB 显存的卡训练时 batch size 要调小后面会讲。如果是RK3588这种边缘平台训练还是在 PC 上做训练完导出 ONNX 再转 RKNN 部署别想着在板子上训。3.2 数据准备与标注规范脏活累活决定上限数据这块我强调三个点划分、清洗、增强。划分训练集、验证集、测试集按 7:2:1 或者 8:1:1 分。注意要按场景分不能随机分。比如你有白天、傍晚、阴天三类场景每一类都要按比例进三个集合。如果随机分可能出现训练集全是白天、验证集全是傍晚的情况验证指标会虚低误导你调参。清洗标注错误比数据少更致命。我见过一个数据集里把“塑料瓶”标成了“其他垃圾”模型学到最后对瓶子特别犹豫。清洗的方法是训一版基础模型用它去预测训练集把预测结果和标注差异大的图挑出来人工复核。这叫“模型辅助清洗”比纯人工看快得多。增强YOLOv8 内置了 Mosaic、MixUp、HSV 抖动、翻转、缩放等增强默认开着。但垃圾分类场景我建议额外加 Copy-Paste 增强——把一张图里的垃圾实例抠出来随机贴到另一张图的空白区域。这对小目标和密集场景特别有效因为真实垃圾桶里就是一堆东西挤在一起。Copy-Paste 需要自己写或者用一些开源增强库。标注规范上有几个细节容易忽略遮挡物体也要标。只要人能判断出是什么哪怕只露出一角也要标。模型需要学会从局部推断整体。边界框贴紧物体。不要留太多空白也不要切掉物体边缘。框太松会让模型学到错误的尺度先验。类别定义要统一。团队标注前先开个会把每个类别的边界案例定清楚写成文档。比如“沾了油的纸盒”算可回收还是其他定一个规则所有人遵守。3.3 模型训练参数每个数字背后的含义YOLOv8 的训练命令长这样yolo detect train datagarbage.yaml modelyolov8n.pt epochs100 imgsz640 batch16 lr00.01我逐个解释关键参数这些是你调参时真正要动的model选yolov8n.ptnano、yolov8s.ptsmall、yolov8m.ptmedium还是更大。n 最快但精度最低m 以上精度高但吃显存。垃圾分类我建议从yolov8s起步它在速度和精度之间平衡得最好。如果显存不够或者要上边缘设备再降到 n。imgsz输入图像尺寸默认 640。这个值直接影响小目标检测能力。垃圾里的小目标烟头、瓶盖在 640 下可能只有几个像素建议提到 800 或 960试试但显存占用会平方级增长。我的经验是如果小目标漏检严重优先提 imgsz比改网络结构见效快。batch批大小。6GB 显存跑 yolov8s imgsz 640batch 设 8 或 16。显存爆了就降别硬撑。可以用batch-1让 Ultralytics 自动找最大可用值但自动找的不一定最优建议手动试几档。lr0初始学习率默认 0.01。这个值对训练稳定性影响很大。如果 loss 一开始就震荡或者爆炸降到 0.001。如果 loss 下降太慢可以适当提到 0.02但别超过 0.1。epochs训练轮数。100 轮是常见起点但要看 loss 曲线。如果验证 loss 在 50 轮后还在降就继续训如果 30 轮就平了甚至反弹说明过拟合了早停。patience早停耐心值默认 50。意思是验证指标连续 50 轮不提升就停。数据少的时候可以调小到 20避免浪费时间。workers数据加载线程数。Windows 上设 0 或 2Linux 上可以设 8。设太大反而慢因为 IO 瓶颈。训练过程中Ultralytics 会在runs/detect/train/下生成一堆文件其中results.csv记录了每轮的 loss 和指标weights/best.pt是验证集上最好的权重weights/last.pt是最后一轮的。部署用 best.pt。3.4 损失函数与评价指标看懂模型在学什么YOLOv8 的损失由三部分组成分类损失BCE、回归损失CIoU、DFLDistribution Focal Loss。分类损失管“是什么”回归损失管“在哪”DFL 是 YOLOv8 引入的让框的回归更精细。评价指标主要看三个Precision精确率预测为正的里面有多少是真的正。高精确率意味着误报少。Recall召回率真实正例里有多少被找出来了。高召回率意味着漏报少。mAP0.5IoU 阈值 0.5 下的平均精度综合指标。mAP0.5:0.95更严格阈值从 0.5 到 0.95 取平均。垃圾分类场景我更看重recall。因为漏检一个有害垃圾比如电池的后果比误检一个可回收物严重得多。所以调参时如果 precision 和 recall 要取舍我偏向保 recall。画 loss 曲线和指标曲线Ultralytics 自带绘图训练完直接看results.png。如果想自己画读results.csv用 matplotlib 画import pandas as pd import matplotlib.pyplot as plt df pd.read_csv(runs/detect/train/results.csv) df.columns df.columns.str.strip() plt.plot(df[epoch], df[train/box_loss], labelbox_loss) plt.plot(df[epoch], df[val/box_loss], labelval_box_loss) plt.legend() plt.show()提示results.csv的列名前后可能有空格读进来先 strip 一下不然取列会报 KeyError。这个坑我踩过。4. 完整实操流程从零到能跑起来4.1 数据组织与配置文件假设你的数据放在datasets/garbage/下结构应该是datasets/garbage/ ├── images/ │ ├── train/ │ ├── val/ │ └── test/ ├── labels/ │ ├── train/ │ ├── val/ │ └── test/ └── garbage.yamlgarbage.yaml内容path: datasets/garbage train: images/train val: images/val test: images/test names: 0: recyclable 1: kitchen_waste 2: hazardous 3: other注意names的 id 必须和标注文件里的类别 id 对应错一个整个训练就废了。4.2 训练脚本与参数设置我一般不用命令行而是写个 Python 脚本方便记录和复现from ultralytics import YOLO model YOLO(yolov8s.pt) results model.train( datadatasets/garbage/garbage.yaml, epochs150, imgsz800, batch12, lr00.01, lrf0.01, patience30, device0, workers8, projectruns/garbage, nameexp1, pretrainedTrue, optimizerSGD, cos_lrTrue, close_mosaic10, )几个参数值得说cos_lrTrue用余弦退火学习率后期收敛更平滑close_mosaic10表示最后 10 轮关掉 Mosaic 增强让模型在真实分布上收尾这个技巧对最终精度有提升optimizerSGD是默认也可以试 AdamW但 SGD 在检测任务上通常更稳。4.3 训练过程监控与调参训练启动后终端会实时打印每轮的 loss 和 mAP。同时可以用 TensorBoard 看更细的曲线tensorboard --logdir runs/garbage我盯训练主要看三件事train loss 和 val loss 的差距。如果 train 一直降、val 早早平了甚至上升就是过拟合该加数据或加正则。mAP 的爬升速度。正常情况前 20 轮涨得快后面变慢。如果 50 轮还在地板检查数据标注和类别配置。显存占用。用nvidia-smi看如果接近满下次降 batch 或 imgsz。调参的顺序我建议先调 imgsz 和 batch受硬件约束再调 lr0最后调增强强度。别一次改多个参数不然出了问题不知道是哪个引起的。4.4 推理与可视化看模型到底学到了什么训练完用 best.pt 跑推理from ultralytics import YOLO model YOLO(runs/garbage/exp1/weights/best.pt) results model.predict(test_image.jpg, conf0.25, iou0.45, saveTrue) for r in results: for box in r.boxes: cls int(box.cls) conf float(box.conf) xyxy box.xyxy.tolist() print(f类别: {model.names[cls]}, 置信度: {conf:.2f}, 框: {xyxy})conf是置信度阈值低于它的预测被丢弃。iou是 NMS 的 IoU 阈值控制重叠框的合并。垃圾分类场景物体密集iou 设太高会保留太多重叠框设太低会误合并相邻物体。我一般从 0.45 起调。可视化方面除了画框强烈建议看热力图。YOLOv8 可以用 Grad-CAM 或者自带的特征图可视化看模型到底关注图像的哪个区域。如果模型盯着背景而不是物体说明数据或训练有问题。热力图还能帮你发现“模型是不是靠颜色作弊”——比如所有蓝色瓶子都被判成可回收但其实是靠颜色而不是形状这种模型换个颜色的瓶子就废了。4.5 模型导出与边缘部署如果要在 RK3588 上跑流程是PyTorch → ONNX → RKNN。导出 ONNXyolo export modelbest.pt formatonnx imgsz640 opset12 simplifyTruesimplifyTrue会做图优化去掉冗余算子。opset12是兼容性比较好的版本。然后 RKNN 工具链把 ONNX 转成 RKNN 模型这一步需要在 x86 的 Linux 机器上做用 RKNN-Toolkit2。转换时要注意量化——RK3588 的 NPU 对 INT8 量化支持最好但量化会掉精度。我的做法是先用少量校准图做 INT8 量化跑一遍验证集看掉多少如果掉超过 3 个点就改用混合量化或者 FP16。部署到板子上之后推理速度能到多少以 RK3588 为例yolov8n 在 640 输入下大概能跑到 30 FPSyolov8s 大概 15-20 FPS。这个速度做实时垃圾分类识别是够用的。5. 常见问题与排查技巧实录5.1 训练不收敛、loss 震荡怎么办这是新手最常遇到的问题。排查顺序现象可能原因解决方法loss 一直是 nan学习率太大、数据有脏标注降 lr 到 0.001检查标注loss 震荡不降batch 太小、lr 太大增大 batch降 lrloss 降但 mAP 不涨过拟合、验证集分布不对加数据增强检查划分某类 mAP 特别低该类样本太少或标注混乱补样本复核标注我遇到过一次 loss 突然变 nan查了半天发现是某张图的标注框坐标超出了 0~1 范围标注时手滑输了个 1.2。YOLOv8 对越界坐标不会报错但会算出异常梯度。所以标注完一定要写个脚本检查坐标范围import os for txt in os.listdir(labels/train): with open(flabels/train/{txt}) as f: for line in f: parts line.strip().split() coords [float(x) for x in parts[1:]] if any(c 0 or c 1 for c in coords): print(f越界: {txt} - {line})5.2 小目标漏检严重怎么破垃圾里的小目标烟头、瓶盖、药片漏检是这类项目的通病。我试过的有效手段按效果排序提高输入分辨率。imgsz 从 640 提到 960小目标像素数翻倍效果立竿见影。代价是显存和推理时间增加。加小目标检测层。YOLOv8 默认在 P3、P4、P5 三个尺度检测可以加一个 P2 层专门抓小目标。这需要改模型结构在ultralytics/nn/modules/head.py里动手。Copy-Paste 增强。把小目标实例复制粘贴到更多位置增加其出现频率。切片推理SAHI。推理时把大图切成小块分别检测再合并结果。适合超高分辨率图像但速度慢。我的经验是先提 imgsz再上 Copy-Paste最后才考虑改结构。改结构风险大容易引入新 bug。5.3 模型在真实场景表现差域偏移问题训练集 mAP 0.9一到真实场景就掉到 0.5这是典型的域偏移。原因通常是训练数据和真实数据的分布不一致——光照、背景、拍摄角度、物体摆放方式都不同。解决办法只有一个字补数据。但补数据有技巧针对性补。分析真实场景里模型错在哪是光照问题就补各种光照的图是遮挡问题就补遮挡图。难例挖掘。用模型跑真实场景图把置信度低或者预测错的图挑出来人工标注后加入训练集。这叫 hard negative mining效果很好。风格迁移。用一些图像风格转换方法把训练图转换成真实场景的风格扩充数据。这个偏研究工程上用得少。我自己的项目里真实场景补了 800 张之后mAP 从 0.52 提到了 0.78效果非常明显。所以别偷懒数据是王道。5.4 部署到边缘设备后的性能问题模型在 PC 上跑得好好的一上 RK3588 就慢或者精度掉常见原因量化掉精度。INT8 量化对某些层敏感可以对这些层保持 FP16。输入尺寸不匹配。导出 ONNX 时的 imgsz 要和部署时一致不然会做额外的 resize。后处理耗时。NMS 在 CPU 上做可能成为瓶颈可以改用 NPU 支持的 NMS 或者优化实现。内存带宽瓶颈。边缘设备内存带宽有限模型太大跑不动该轻量化就轻量化。提示RK3588 部署时建议先用官方提供的 yolov8 demo 跑通再替换成自己的模型。这样能把“环境问题”和“模型问题”分开排查。5.5 常见问题速查表问题排查方向快速验证训练报 CUDA out of memorybatch/imgsz 太大降 batch 到 4 试mAP 为 0类别 id 不匹配检查 yaml 和标注推理结果全是同一类数据不平衡统计各类样本数框位置偏移标注格式错误可视化标注框导出 ONNX 失败opset 版本问题换 opset 11 或 13边缘设备推理慢未量化或输入太大用 INT8 6406. 几个值得试的改进点与我的实测反馈6.1 插入 CoordAtt 注意力改哪里、怎么改CoordAtt 的插入位置我试过三个地方backbone 末端、neck 的每个融合节点后、head 前。实测下来插在 neck 的 P3 和 P4 融合节点后效果最好因为这两个尺度对应中小目标正是垃圾检测的难点。改法是在ultralytics/nn/modules/block.py里加 CoordAtt 类然后在parse_model里注册。具体代码网上有很多参考核心是把输入特征在 H 和 W 两个方向分别做平均池化拼接后过卷积和激活再拆开做注意力权重。改完记得重新训别指望加载旧权重直接涨点。我的实测yolov8s CoordAttmAP0.5 从 0.82 提到 0.85小目标 recall 提升约 6 个点。代价是推理速度降了约 8%可以接受。6.2 损失函数换 WIoU回归更稳CIoU 在处理低质量样本标注框和预测框偏差大时梯度会被放大训练不稳定。WIoUWise IoU通过动态调整样本权重让模型更关注普通质量样本。替换方法是在ultralytics/utils/metrics.py里改bbox_iou函数或者在损失计算处替换。我的实测换 WIoU 后训练前期 loss 下降更平滑最终 mAP 提升约 1.5 个点。提升不算大但训练稳定性改善明显值得一试。6.3 数据增强的组合拳除了默认增强我加了两个随机遮挡。随机在图上贴几个黑色小方块模拟遮挡。这能提升模型对遮挡物体的鲁棒性。亮度对比度扰动。模拟不同光照条件。垃圾分类经常在户外光照变化大这个增强很实用。这两个增强用 albumentations 库实现然后在 YOLOv8 的 dataloader 里挂上去。注意增强强度别太大否则模型学不到真实分布。7. 我踩过的坑和给你的建议这个项目我从头到尾做了大概三个月中间踩的坑不少挑几个最有代表性的说。第一个坑一开始贪多做了 20 类。结果每类样本只有几十张模型学得一塌糊涂。后来砍回 4 类每类补到 500 张效果立刻好转。类别数要和数据量匹配这是铁律。第二个坑验证集和训练集场景重叠。我一开始随机划分结果验证集里很多图和训练集是同一场景拍的mAP 虚高到 0.95一上真实场景就露馅。后来按场景划分验证 mAP 降到 0.78但这才是真实水平。验证集要能代表真实分布不然就是自欺欺人。第三个坑忽略推理速度。我一开始用 yolov8m精度是高但在 RK3588 上只能跑 5 FPS根本没法实时。后来换 yolov8n 量化跑到 30 FPS精度只掉了 2 个点。部署目标决定模型选型别等训完了才发现跑不动。第四个坑标注质量参差不齐。团队三个人标每个人对边界的理解不一样导致同一类物体框的大小差异很大。后来统一了标注规范还做了交叉复核才解决。标注规范要写成文档标注完要抽检。最后分享一个实用技巧用模型辅助标注。训一版基础模型用它去预标注新数据人工只需要修正错误的框比从零标快 3 到 5 倍。这个技巧在数据量大的时候特别管用能省下大量时间。这个方向后续还能扩展的地方很多比如加入时序信息做视频流垃圾分类连续帧的检测结果做投票提升稳定性或者结合机械臂做自动分拣再或者用开放词汇检测让模型能识别训练时没见过的垃圾类别。这些都是有意思的方向等基础版本跑稳了可以逐步尝试。