
1. 为什么毕业设计选了垃圾分类识别一个被低估的深度学习课题每年到了毕设开题季总有同学在图像分类目标检测人脸识别这些经典题目之间反复横跳。我当年做毕设时也面临同样的选择最后敲定的方向是基于深度学习的垃圾分类识别系统。说实话刚开始我也觉得这题目有点土——垃圾分类听起来像是个偏工程、偏业务的东西深度学习含量似乎不够高。但真正把需求拆开之后才发现这个题目简直是麻雀虽小、五脏俱全的典范它既有标准的图像分类任务作为基线又有目标检测的进阶空间还牵扯到数据增强、模型压缩、推理部署、UI交互等一系列完整链路。换句话说做这个题目你不是在完成一个毕设而是在走一遍完整的AI落地流程。这对找工作和复试都有实打实的说服力。而且它的门槛相对友好公开数据集好找、评估指标直观、展示效果好评委老师一看就懂。相比某些偏门课题垃圾分类识别属于那种下限有保障、上限有空间的安全牌。这篇文章就围绕我当时做这套系统的完整思路展开包括数据怎么准备、模型怎么选、训练踩了哪些坑、部署和界面怎么做以及针对如何答辩讲清楚给出一些实操建议。如果你正在纠结毕设选题或者已经选了类似题目但还没理清技术路线这篇文章应该比你在网上随便搜到的源码分享帖更有参考价值。先交代一下技术选型结论分类部分我用了ResNet50 的迁移学习方案检测部分用YOLOv5s 做二次识别GUI 基于PySide6实现最终打包成一个离线可运行的桌面程序。这套组合不是拍脑袋定的下面我会逐步解释每一层选择背后的理由。2. 数据集与类别体系从四分类还是多分类这个灵魂问题开始2.1 分类体系设计的决策逻辑做垃圾分类识别第一个绕不开的问题是究竟分几类最常见的选项是两种四分类可回收垃圾、厨余垃圾、有害垃圾、其他垃圾——这是国内社区垃圾桶的经典配置贴近真实场景但类间差异其实很大其他垃圾几乎是个垃圾筐什么都能往里装模型学起来容易懵。多分类如 40 类按具体物品细分比如塑料瓶、易拉罐、玻璃、纸板、电池、药片等。训练难度更高但对系统能力的体现更充分。我当时的选择是多分类作为主模型、四分类作为辅助映射。也就是说模型先识别出这是塑料瓶再通过预设映射表把它归类为可回收垃圾。这样做有两个直接好处一是算法的判别能力体现得更充分答辩时有内容可讲二是最终呈现在界面上的结果仍然是可回收垃圾这种用户能直接理解的类别不会出现AI识别出PE塑料然后用户一头雾水的情况。2.2 数据获取与清洗的实操经验数据集方面公开资源里最常用的是华为云垃圾分类数据集和Kaggle上的垃圾分类相关集合。华为云那版大概有几万张图片覆盖了常见的生活垃圾。但直接拿过来训练会有一个看起来没问题、实际很致命的隐患——大量图片是纯色背景下的商品图而真实场景中的垃圾往往是皱巴巴的、脏兮兮的、被遮挡的。如果你训练的模型只在干净背景上表现好确实测起来很准但换到真实拍摄的照片就立刻原形毕露。我的做法是这样先按类别把数据集拆开人工筛掉模糊、重复、标注错误明显的图片对每一类确保数量不低于 300 张不足的类通过爬虫抓取后二次清洗补齐把大概 10% 的干净背景图片替换成生活场景图——比如桌面上的外卖盒、草地上的矿泉水瓶、厨房水槽里的菜叶子。这类图片让模型更容易学到纹理而非背景。数据增强方面我用的组合是随机水平翻转、随机旋转±15度、随机亮度/对比度扰动、随机裁剪缩放0.8到1.2倍以及少量高斯噪声。有一件事值得特别注意不要对垃圾分类任务使用随机垂直翻转。因为瓶子和罐子倒过来放语义上依然是塑料瓶但真实场景中垃圾很少出现倒挂视角的拍摄。强行增强只会增加模型的学习负担。这个细节很多教程不会提但影响挺实在的。3. 模型选型的真实对比从轻量模型到迁移学习3.1 为什么没选MobileNetV3作为主模型在定下 ResNet50 之前我其实先试过 MobileNetV3。它的优势非常明显参数量小、推理快、对CPU友好。我在同一批数据上做过对比实验MobileNetV3 在验证集上的准确率大概在 88% 左右而 ResNet50 能达到 93% 上下。差距主要出现在那些形态相似的类别上比如纸杯和纸盒以及不同颜色的玻璃瓶。轻量模型为了压缩计算量牺牲了部分细粒度特征的表达能力在类别数超过 20 时这个差距会被明显放大。但我也不是完全否定了轻量模型的价值。如果你的毕设要求不高或者打算部署到树莓派这类边缘设备上那么 MobileNetV3 依然是一个合理的基座方案。做技术选型时先明确算力约束和使用场景再谈模型性能否则讨论都是在空转。3.2 ResNet50 迁移学习的完整配置我的最终方案是加载 ImageNet 预训练权重的 ResNet50替换全连接层后微调。具体配置如下输入尺寸224×224优化器Adam初始学习率 0.0001权重衰减1e-4批次大小32训练轮数20 轮先用冻结 backbone 的方式跑 5 轮再解冻全部层微调 15 轮学习率调度余弦退火最低降到 0.00001这里有一个值得展开的点学习率为什么要这么低因为预训练模型已经学到了通用的底层特征比如边缘、纹理、颜色分布。过大的学习率会把已经学好的特征冲掉通常表现为训练集准确率快速上升但验证集准确率却停滞不动。我第一次跑的时候用了 0.001结果验证集一直在 90% 上下徘徊改成 0.0001 之后第二轮就到了 93%。这类经验只有自己踩过才会印象深刻。# 核心训练代码片段PyTorch import torch import torch.nn as nn import torchvision.models as models model models.resnet50(weightsmodels.ResNet50_Weights.IMAGENET1K_V2) num_features model.fc.in_features model.fc nn.Linear(num_features, num_classes) # 前5轮冻结backbone for param in model.parameters(): param.requires_grad False for param in model.fc.parameters(): param.requires_grad True冻结 backbone 的训练方式非常适合数据量不太大的场景。它相当于让模型在原有视觉常识的基础上只补学一套垃圾分类专用分类头既能防止过拟合又能显著缩短前期收敛时间。4. 识别精度与误判处理YOLOv5 用来解决什么问题4.1 纯分类模型的软肋如果只做图像分类这套系统会存在一个明显短板模型只能告诉你图片里大概率是什么但它压根不知道物体在哪里。当你把一张包含多个物品的照片扔进去分类模型只会输出一个标签而这张照片里可能同时有塑料瓶和纸盒。解决这个问题有两个方向改成目标检测直接输出多个物体的位置和类别保留分类模型但增加一个前置的目标提取步骤。我当时选的是第二种思路的加强版先用 YOLOv5s 做检测把检测到的每个物体裁剪出来再分别送入 ResNet50 做精细分类。为什么不是直接用 YOLOv5 输出最终类别因为 YOLOv5 自带的类别体系不一定覆盖你想要的垃圾细分类比如奶茶杯和塑料袋在某些检测数据集里可能属于 A 类或其他语义粒度不够。用两级结构我既保留了检测的定位能力又拿了分类模型的细粒度判别。4.2 YOLOv5s 训练与参数细节YOLOv5s 是这套模型系列里体积最小的版本参数量约 700 万GPU 上单卡能跑得动CPU 推理也不算太慢。我训练的配置如下输入分辨率640×640批次大小16epoch50 轮优化器SGD初始学习率 0.01数据标注用 LabelImg 手动框了大概 4000 个目标框训练 YOLO 时有一个最容易忽视的点anchor 的自动重聚类。官方代码默认会在训练前自动计算数据集的 anchor 尺寸但如果你换了数据集之后把 autoanchor 关掉了模型收敛会变得很慢甚至 mAP 上不去。我第一次训练时就遇到了这个情况训练到第 20 轮损失还是下不来排查后才发现是锚框尺寸和数据严重不匹配。4.3 误判率最高的几个类别及补救手段实际跑测试时误判率最高的几组是干净的纸盒 vs 脏的纸盒、透明塑料袋 vs 白色塑料瓶、浅色玻璃瓶 vs 白色陶瓷。前两组容易理解第三组很有意思——分类模型看到的主要是颜色、光泽和形状玻璃和陶瓷在某些拍摄角度下几乎无法区分。补救手段我做了两个方向采集更多脏污/褶皱/光线变化的样本加入训练集让模型不只靠颜色光滑度做判断在系统界面中增加人工确认按钮。当模型输出概率低于某个阈值比如 0.7时系统提示用户二次确认或手动选择类别。这不是模型层面的解决方案但它在现实使用中非常必要因为垃圾分类识别这个场景本身就存在人都不一定看得准的边界案例。注意分类模型输出的 softmax 概率并不直接等于真实置信度。Softmax 是相对概率分布它会强制所有类别相加为 1即使样本属于未知类别模型也必须给一个相对最高的类别。所以阈值设置只能作为一个参考信号不能当作严格的不确定性估计。5. 界面与工程落地PySide6 桌面应用是怎么搭起来的5.1 为什么用 PySide6 而不是 Flask Web毕设展示环节很多同学会选择做一个 Web 页面因为部署简单、演示灵活。但我的需求里有一条系统需要在无网络环境下运行。教室、实验室现场的 WiFi 不稳定如果依赖 Flask 启动一个本地服务再通过浏览器访问一旦服务端口被占用或者浏览器缓存异常展示就会出状况。桌面应用反而更稳妥——双击打开、选择图片、出结果完了。PySide6 是 Qt 的 Python 绑定界面写起来比 Tkinter 舒服又有成熟的打包工具链。整个过程下来我觉得最舒服的一点是它的信号槽机制让界面操作和模型推理逻辑能解耦。5.2 推理线程的设计卡UI是最大的坑如果你直接在按钮的回调函数里跑模型推理一旦图片比较大界面就会冻结拖拽窗口时会变成无响应。这个体验对答辩来说是灾难性的。我的解决方案是用 QThread 单独开一个工作线程模型加载和推理都放在线程里主线程只负责接收结果并更新界面。大概的代码框架是这样的from PySide6.QtCore import QThread, Signal class InferWorker(QThread): finished Signal(str, float) # 类别置信度 def __init__(self, image_path, model, transform): super().__init__() self.image_path image_path self.model model self.transform transform def run(self): result predict(self.image_path, self.model, self.transform) self.finished.emit(result[0], result[1])这样处理后即便推理耗时一两秒界面也始终能正常响应。实现成本很低但体验提升非常明显。我还在界面上加了三样东西置信度进度条直观展示模型对结果的自信程度映射表展示多分类结果映射到四分类后显示对应颜色标识绿色可回收灰色其他红色有害等批量识别用户可上传整个文件夹系统逐个识别并导出一个 CSV 表格。6. 训练与调参过程中的五个印象深刻的坑6.1 类别不平衡某些类别占了50%的训练数据公开数据集里易拉罐和塑料瓶这类常见垃圾图片非常多而打火机温度计这类不常见样本可能只有几十张。直接训练会导致少数类别几乎从来没被正确预测过。处理方式包括将大类随机下采样小类通过复制加轻微扰动的方式过采样使用加权采样器WeightedRandomSampler让每个 epoch 中各类别抽到样本的期望次数接近相等在损失函数中给少数类更高的权重。我当时用的是 Focal Loss 的简化版本对难样本更聚焦。6.2 过拟合特征背景泄漏的经典陷阱有一类常见错误极具迷惑性——模型不是靠垃圾本身而是靠背景来分类。比如树叶类样本很多是绿地背景模型学到的特征是绿色而不是树叶纹理。测试时你会看到准确率不错但把一张草地上拍的可乐罐扔进去它可能也报树叶。这个问题怎么自查把训练集里某几张图片的物体抠出来贴到纯白背景上再测试。如果模型输出突变很大说明它高度依赖背景特征。解决思路还是一样增加背景多样性或者用目标检测先裁剪物体区域再分类这两种手段都能有效缓解。6.3 推理速度比预期慢CPU 上的优化空间ResNet50 在 GPU 上推理很快但很多同学的毕设演示环境根本没有独立显卡CPU 跑一张图可能需要 800ms 到 1.5 秒。为了优化我做了这几点使用 ONNX Runtime 替代纯 PyTorch 推理在 CPU 上通常能快 20%~40%将输入尺寸从 224 适当缩到 192准确率几乎不掉但推理加快开启单线程和多线程的平衡调整Intel CPU 上把 intra-op 线程数设为物理核心数推理延迟可控。6.4 显存溢出小显存卡怎么训练实验室如果只有 4GB 显存的卡训练 ResNet50 加 YOLOv5s 会比较紧张。方案是开启梯度累积每 4 个 batch 更新一次参数等效于扩大 batch size混精度训练AMP要让 ResNet50 跑到 224 分辨率混精度之后显存占用能降 30% 左右如果还不行把 ResNet 输入降到 192或者考虑 ResNet34。6.5 打包体积膨胀PyTorch 打包出来的 exe 有 1.5GB 以上用 PyInstaller 打包 PyTorch 应用体积会非常夸张。我最终做的是用 ONNX 模型替代 PyTorch 模型文件再配合精简依赖打包体积从 1.5GB 降到了大概 400MB。这一步在整个工程化落地里性价比极高。不同版本的 ONNX Runtime 对 CPU 指令集的要求略有差异建议在目标演示机上先跑一个最小测试程序确认可以正常加载。7. 如何把毕设讲出亮点答辩角度的叙事思路很多同学做完了系统但答辩时只会说我用了 ResNet50 和 YOLOv5准确率 93%。这远远不够。评委更希望听到的是你面对具体问题时的决策过程。以下是我当年准备的几条叙事主线供参考我为什么没一上来就用最重的模型——先说 MobileNetV3 的尝试与瓶颈再引出 ResNet50 的选型理由体现你做过对比实验分类准确率不是唯一指标——补充说明结果显示和阈值机制的设计体现你考虑过真实使用场景数据是模型的起点——多提数据清洗、类别不平衡、背景泄漏问题说明你理解深度学习项目的工程全貌而非只会调库训练性能优化经历了从 PyTorch 到 ONNX Runtime 的转变——展示你对部署环节的认识这在问到以后还能怎么改进时尤其加分。答辩时实测演示一定要提前准备三张图一张标准场景图、一张多物体混合图、一张容易误判的模糊图。前两张展示正常能力第三张展示置信度阈值控制逻辑反而比全程准确更能说明你的思考深度。8. 还可以怎么扩展从毕设到真正可用的系统毕设做完了但不代表这套系统的潜力到头了。它至少还有三个方向的扩展空间硬件方向把模型部署到树莓派加摄像头做成拍照识别即分类的嵌入式设备。由于模型已经是 ONNX 格式Raspberry Pi 上跑起来不算困难只需要把主干网络换得更轻量一些算法方向从识别模型升级为识别定位拆分的联动方案或者针对易混淆类玻璃瓶 vs 陶瓷、纸盒 vs 纸杯单独训练一个细粒度分类模型作为第二级校验数据方向设计一个小型的增量学习流程让用户在界面上纠正错误分类结果系统定期把纠错数据加入训练集重新微调。这个功能一旦做出来系统就不再是静态固化的模型而是能随着使用逐步优化的闭环系统。我在实际做扩展实验时发现最简单的增量微调方式是用户每次点击人工纠正时把当前图片和正确标签保存到一个本地文件夹累积到 200 张后触发一次低学习率微调。这个流程不复杂但能让毕设成果在答辩时讲出一个非常漂亮的持续学习故事。做这个毕设时我最有体会的一点是深度学习项目的核心竞争力往往不在模型选型本身而在你对数据的理解和对应用场景的把握。垃圾分类识别看起来是个老旧的课题但当它被放在一个完整系统中去思考你会发现它牵引出的每一个技术节点——数据增强、迁移学习、目标检测、模型压缩、GUI 工程化——都值得深挖两三层。选一个麻雀虽小五脏俱全的题目用心做完它给你的训练绝不亚于一个表面花哨的大项目。