
简介本资源是一套面向高校计算机类专业学生的Python垃圾分类系统实战项目适用于毕业设计、课程设计及人工智能方向期末大作业等实践场景聚焦图像识别与环保应用结合的技术落地。压缩包共24个文件含7个核心Python脚本如classify.py、garbage.py、ui.py等、3个UI界面文件.ui、3个数据集压缩包cardboard.zip、plastic.zip、trash.zip、1个C测试备份文件.cpp.zbak及README.md等说明文档整体61.16MB结构清晰模块划分明确——涵盖前端交互、后端逻辑、模型调用与数据预处理全流程。已有41人学习下载项目曾获课程设计评审98分并经指导教师审核认证配套完整开发文档与实现代码包含界面设计截图、功能流程图、数据集组织规范及模型训练方案可直接部署调试为AI环保类课题提供可复用的工程化参考范例。 不知道你有没有过这种瞬间——站在楼下垃圾桶前手里拎着外卖盒、快递箱和剩下的半个西瓜先看一眼桶上的标识再低头瞄一眼手机搜索最后还是凭感觉扔进去了。说实话我自己就纠结过很多次后来干脆花了两个周末用Python做了一个垃圾分类系统拍照识别垃圾类别几秒钟给你准确答案。项目本身不复杂但麻雀虽小五脏俱全从数据集、模型训练到Web部署一整条流水线都是完整的而且源码直接开源改一改就能变成你自己的项目。这篇文章我就把整套Python垃圾分类系统的实现方案摊开讲。我会把项目定位、技术选型、环境搭建、模型训练、API服务、前端页面和部署优化全流程过一遍中间穿插我在实际开发中踩过的坑和调整思路。不管你是刚学Python想做课设还是想系统入门图像分类项目这套代码和方案都能直接复用。1. 项目定位垃圾分类系统到底解决了什么问题1.1 别急着写代码先想清楚这个系统要做什么很多人在拿到垃圾分类系统这个题目时第一反应就是这不就是个图像分类吗套个CNN不就行了。理论上是这样但真要把系统落地需要回答的问题远不止分类本身。我在动手前先列了一份需求清单用户怎么使用这个系统网页上传图片还是摄像头实时识别识别出结果之后要展示什么只告诉类别还是连投放指导一起给出分类体系怎么定四分类可回收、厨余、有害、其他还是细分到具体垃圾名称模型跑在哪里本地推理还是部署到服务器谁在用这个系统如果是教学演示速度和精度哪个优先级更高这些问题看似简单却决定了整个项目的架构方向。如果目标只是交一个课设那张静态图片命令行输出的方案就够了但如果你想把它做成一个真正能用的小工具前端交互、模型推理、异常处理、部署方式就都得考虑进去。我这里最终确定的是一个Web形式的最小可用产品用户通过浏览器上传一张垃圾图片后端调用训练好的深度学习模型进行识别返回垃圾类别名称、所属分类、投放建议和置信度。整个项目包括训练脚本、数据集处理脚本、Flask后端、简单前端页面和部署配置完整闭环开箱即用。1.2 这套源码的整体架构和核心模块项目的目录结构一开始就要规划好不然训练到一半你会被各种脚本和权重文件搞得晕头转向。我最终整理出来的结构是这样的garbage_classification/ ├── app.py # Flask 后端入口 ├── requirements.txt # 项目依赖 ├── config.py # 全局配置 ├── data/ │ ├── train/ # 训练集按类别分文件夹 │ └── val/ # 验证集 ├── models/ │ ├── model.py # 模型定义 │ └── efficientnet_finetuned.h5 # 训练好的权重 ├── src/ │ ├── train.py # 训练脚本 │ ├── predict.py # 单张图片预测脚本 │ ├── data_augmentation.py # 数据增强脚本 │ └── preprocess.py # 数据预处理与划分 ├── templates/ │ └── index.html # 前端页面 └── static/ ├── css/ └── uploads/ # 用户上传的图片存放处数据目录按类别分文件夹存放这是图像分类任务最常见的组织方式。每个文件夹名就是类别名训练脚本会自动扫描所有子目录生成标签映射后期增加新类别只需要往文件夹里丢图片不需要改代码。后端服务我选了Flask而不是Django原因很直接项目规模小只需要一个上传接口和一个预测接口Flask的轻量灵活完全够用而且Flask的路由和request处理逻辑非常直白源码容易读懂对初学者友好。后续如果要扩展用户系统并发处理再把Flask换掉也不迟。2. 技术选型对比深度学习方案的四个关键选择2.1 为什么必须用深度学习而不是OpenCV传统方法接到垃圾分类这个需求我先想到了OpenCV加传统图像处理的做法提取颜色直方图、纹理特征、边缘形状再丢给SVM或者随机森林分类。这个思路在十年前的论文里很常见对背景单一的图片确实有效但一放到真实场景就露馅了。举个例子一个透明的矿泉水瓶和一个玻璃瓶颜色上都是透明偏绿形状上都是圆柱体纹理特征更是相似。人眼可以靠高光的折射、瓶身标签、瓶口螺纹这些细微线索来区分但传统手工特征很难把这些信息编码进去。更麻烦的是垃圾种类五花八门从剩菜到纸箱到电池外观差异极大靠人工设计特征维度的方案可维护性很差。深度学习特别是卷积神经网络的优势在于它不需要你手动设计特征网络会自己从数据中学出什么样的外观模式对应哪个类别。今天它学到的是瓶身螺纹和高光折射的关联明天换一批新数据它也能自己调整。所以整个方案的关键决策之一就是用数据驱动代替人工特征工程。2.2 模型选型MobileNet、ResNet还是EfficientNet确定了用CNN之后马上迎来的问题是用什么网络结构。我在项目中实际对比了三种主流模型最终选定的是EfficientNet和MobileNet的组合路线。下表是当时参考的对比数据模型参数量Top-1准确率ImageNet推理速度移动端适配性适合场景ResNet5025.6M75.99%中等一般通用任务、服务器端MobileNetV35.4M75.20%极快很好移动端、嵌入式设备EfficientNetB05.3M77.10%较快好精度优先的轻量场景VGG16138M71.53%慢差学术研究、特征提取从准确率、参数量、推理速度三个维度综合看EfficientNetB0和MobileNetV3都明显优于老牌ResNet和VGG。考虑到这套系统以后可能会部署到手机端或者树莓派上我没有选择一个大而重的模型而是选了EfficientNetB0作为主干。它的提特征效率比同等大小的网络更高对硬件要求相对友好训练时间也不会太长。实际项目中我还做了另一个小技巧先用迁移学习加载ImageNet预训练权重再把全连接层替换成垃圾类别数量对应的输出层。这样做起步准确率就高训练迭代次数可以大幅缩短。注意模型选型没有绝对标准关键是匹配部署场景。如果只在PC上跑演示ResNet50也完全没问题如果后续要上AndroidMobileNetV3的优先级别更高。2.3 数据集用公开数据集还是自己标注垃圾分类相关的公开数据集其实不算稀缺。常见的有华科大的40类垃圾分类数据集、Kaggle上的Garbage Classification数据集以及各种新闻报道里配套的图片集。我最终用的是包含40个类别的公开数据集涵盖玻璃、塑料、金属、纸张、纸板、厨余垃圾、有害垃圾等大类。选数据集时我特别留意了两件事。第一是类别要平衡如果可回收垃圾图片有5000张有害垃圾只有200张模型会对大类过拟合、对小类欠拟合。第二是图片质量网上下载的图片分辨率参差不齐有的还带水印这些都需要统一预处理。如果你准备自己做数据集我会建议从Google图片下载脚本起步再人工清洗一轮无效图最后每个类别至少300张以上再考虑训练。另外关键一点验证集和训练集不要来自同一个拍摄批次不然模型记住的是拍摄环境而非物体本身验证分数会虚高。2.4 框架选型TensorFlow还是PyTorch这个选择在开发社区里争论了很久但我个人倾向非常明确这个项目用TensorFlow/Keras实现。原因不是PyTorch不好而是对于Web端部署TensorFlow SavedModel格式配合Flask或者TensorFlow Serving都要成熟很多。Keras的高层API写demo模型速度极快几行代码就能完成数据增强和模型训练非常适合快速出一版可用系统。当然如果你是PyTorch的忠实用户用TorchServe或者ONNX导出效果也是等价的。关键是选一个你熟悉的框架不要花时间在临阵换框架上。项目中我用了TensorFlow 2.x版本来实现下面的代码示例也按这个框架写。3. 环境配置与快速启动从零跑通这套源码3.1 Python环境准备与依赖清单很多人第一步就被环境卡住了。这里我把一套干净可复现的环境准备步骤写出来照着执行即可。系统环境我用的Windows 10Python 3.9原因无他——TensorFlow在3.9上的支持最稳定很多老版本的坑在3.10之后都冒出来了。如果你之前装过其他Python版本建议用虚拟环境隔离# 创建虚拟环境 python -m venv garbage_env # 激活虚拟环境Windows garbage_env\Scripts\activate # 激活虚拟环境Linux/macOS source garbage_env/bin/activate创建完虚拟环境后我需要确认pip源。国内访问官方源经常慢得让人抓狂建议直接切国内镜像pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip依赖安装方面完整的requirements.txt我贴出来tensorflow2.10.0 keras2.10.0 flask2.2.2 opencv-python4.6.0.66 numpy1.23.5 pandas1.5.2 matplotlib3.6.2 pillow9.3.0 tqdm4.64.1 gunicorn20.1.0特别提醒一下这里TensorFlow和Keras的版本必须严格对应。TensorFlow 2.10之后Keras已经内置在tf.keras中不需要单独pip install keras如果你自己安装了一个新版keras反而会导致版本冲突报错。如果条件允许建议直接用GPU版TensorFlow训练速度快非常多。3.2 数据准备与预处理脚本数据集下载好之后第一步是统一尺寸和格式。我们的EfficientNetB0模型接收的输入尺寸是224x224所以所有图片都要缩放或裁剪到这个尺寸。一般来说我会把原始图片先等比缩放到短边256像素再中心裁剪到224x224。这样既保留了主体信息又不会因为强行拉伸让物体变形。数据划分的代码我放到src/preprocess.py中核心逻辑是把原始数据集按8:1:1划分为训练集、验证集和测试集。为了让读者能调试我特意用了最简单的shutil复制文件方式没有引入复杂的生成器import os import shutil import random def split_dataset(source_dir, target_dir, train_ratio0.8, val_ratio0.1): 把source_dir下的类别文件夹划分到 train/val/test for class_name in os.listdir(source_dir): class_path os.path.join(source_dir, class_name) if not os.path.isdir(class_path): continue images os.listdir(class_path) random.shuffle(images) train_count int(len(images) * train_ratio) val_count int(len(images) * val_ratio) for phase, phase_images in zip( [train, val, test], [images[:train_count], images[train_count:train_count val_count], images[train_count val_count:]] ): dst_dir os.path.join(target_dir, phase, class_name) os.makedirs(dst_dir, exist_okTrue) for img in phase_images: src os.path.join(class_path, img) dst os.path.join(dst_dir, img) shutil.copy(src, dst)这里有一个非常容易踩的坑文件重名。如果不同来源的图片有相同的文件名复制到同一个目录时可能会被覆盖。我在实际项目中加了一步把图片文件名统一改为时间戳随机数后再复制能彻底避免这种问题。3.3 数据增强小数据集逆天改命的核心垃圾分类数据集的图片数量通常不够大如果用原始数据直接训练过拟合几乎是必然的。我的做法是引入一套完整的数据增强流程包括随机旋转、翻转、亮度调整、对比度调整、缩放和剪切变换。增加简单数据增强的代码长这样from tensorflow.keras.preprocessing.image import ImageDataGenerator train_datagen ImageDataGenerator( rescale1.0/255.0, rotation_range30, # 随机旋转 ±30度 width_shift_range0.2, # 水平平移 20% height_shift_range0.2, shear_range0.2, # 剪切变换 zoom_range0.2, # 随机缩放 horizontal_flipTrue, # 水平翻转 brightness_range[0.8, 1.2], # 亮度调整 fill_modenearest ) val_datagen ImageDataGenerator(rescale1.0/255.0)我记得第一次训练时偷懒没加数据增强训练集准确率刷到98%了验证集只有70%典型的过拟合。加上旋转和翻转之后验证集准确率直接拉升到89%左右。如果你之前的项目准确率一直上不去数据增强绝对是你第一个要检查的环节。4. 核心功能实现训练模型与搭建API的完整流程4.1 迁移学习与模型定义细节模型定义这块我采用迁移学习的标准流程。先加载EfficientNetB0的ImageNet预训练权重去掉顶层分类器然后在上面接一个全局平均池化层、一个Dropout层和一个Dense输出层。为什么加全局平均池化层因为它可以把任意尺寸的特征图压缩成一维向量相当于把空间信息分区域取平均能显著降低过拟合风险。模型定义的核心代码如下import tensorflow as tf from tensorflow.keras.applications import EfficientNetB0 from tensorflow.keras import layers, models def build_model(num_classes): base_model EfficientNetB0( weightsimagenet, # 加载预训练权重 include_topFalse, # 去掉顶层分类器 input_shape(224, 224, 3) ) base_model.trainable False # 先冻结底层 model models.Sequential([ base_model, layers.GlobalAveragePooling2D(), layers.Dropout(0.2), layers.Dense(num_classes, activationsoftmax) ]) return model这里我特意把base_model.trainable设为False也就是先冻结主干网络的所有层。这样刚开始训练时只有新加的Dense层在更新参数相当于在预训练模型的特征基础上做线性打分训练速度快且不容易把预训练权重破坏掉。等新加的分类层训练得差不多了再解冻最后几层用一个很小的学习率做联合微调。这套先冻结后解冻的老套路在图像分类上极其经典也是我强烈建议调试者采用的方式。4.2 训练参数解读与全程记录训练阶段的超参数设置直接决定最终效果。我把当时用到的关键参数整理出来并说明它们的实际作用。参数值作用与依据输入尺寸224x224EfficientNetB0原生输入尺寸Batch Size32兼顾显存占用与收敛稳定性Epochs50设早停回调防止过拟合优化器Adam自适应学习率收敛快初始学习率0.0001迁移学习微调阶段宜小损失函数CategoricalCrossentropy多分类标准损失早停参数patience5连续5轮验证集不提升则停止这里特别注意学习率。很多人喜欢用默认的0.001甚至更高但在迁移学习场景下这几乎是灾难因为预训练模型的权重已经很好了过大的学习率会像急刹车翻车一样把原有知识破坏掉。我通常把微调阶段的学习率控制在0.0001到0.00001这个区间稳妥得多。训练脚本的核心部分from tensorflow.keras.callbacks import EarlyStopping, ModelCheckpoint, ReduceLROnPlateau model.compile( optimizertf.keras.optimizers.Adam(learning_rate0.0001), losscategorical_crossentropy, metrics[accuracy] ) callbacks [ EarlyStopping(patience5, restore_best_weightsTrue), ModelCheckpoint(models/best_model.h5, save_best_onlyTrue), ReduceLROnPlateau(factor0.5, patience3, min_lr1e-7) ] history model.fit( train_generator, steps_per_epochtrain_generator.samples // 32, epochs50, validation_dataval_generator, validation_stepsval_generator.samples // 32, callbackscallbacks )这套配置跑起来之后我记录的训练曲线大概是这样前5个epoch验证集准确率就冲上了75%左右说明预训练权重提供了很好的起点等解冻主干网络的最后20层再微调10个epoch验证集准确率稳定在90%以上。如果你的数据集更小可以适当增加Dropout强度或者加入L2正则项来防过拟合。提示ModelCheckpoint里的save_best_only一定要开不然训练50轮可能把最好的权重覆盖成一个中途的差权重。restore_best_weights参数和早停搭配能确保最后留在内存里的是验证集最优状态。4.3 Flask API把模型封装成服务模型训练好之后下一步就是把模型变成可以被用户调用的接口。Flask这边我写了两个路由一个处理首页展示一个处理图片上传与识别。核心的预测接口实现如下import os import numpy as np from flask import Flask, request, jsonify, render_template from tensorflow.keras.models import load_model from tensorflow.keras.preprocessing import image app Flask(__name__) model load_model(models/best_model.h5) class_name [厨余垃圾, 可回收物, 其他垃圾, 有害垃圾] category_info { 可回收物: 请投入蓝色垃圾桶包括纸张、塑料、金属、玻璃等, 厨余垃圾: 请投入绿色垃圾桶包括剩菜剩饭、果皮、茶渣等, 有害垃圾: 请投入红色垃圾桶包括电池、灯管、药品等, 其他垃圾: 请投入灰色垃圾桶包括砖瓦陶瓷、渣土、卫生间废纸等 } def classify_garbage(img_path): img image.load_img(img_path, target_size(224, 224)) img_array image.img_to_array(img) img_array np.expand_dims(img_array, axis0) / 255.0 pred model.predict(img_array)[0] idx int(np.argmax(pred)) confidence float(pred[idx]) return class_name[idx], confidence app.route(/, methods[GET]) def index(): return render_template(index.html) app.route(/predict, methods[POST]) def predict(): file request.files.get(image) if file is None: return jsonify({error: 未上传图片}), 400 file_path os.path.join(static/uploads, file.filename) file.save(file_path) result, confidence classify_garbage(file_path) return jsonify({ label: result, category: result, confidence: round(confidence, 4), advice: category_info.get(result, ), image_url: file_path }) if __name__ __main__: app.run(host0.0.0.0, port5000, debugTrue)这里有几个细节值得注意。第一模型加载放到全局变量区域只加载一次最好不要在每次请求时重新load_model因为模型加载时间比推理时间长得多。第二图片预处理必须和训练时保持一致都缩放成224x224并且除以255归一化。第三上传文件要做路径安全校验不然用户可以直接传一个路径符号搞目录穿越虽然演示项目无所谓但习惯要养好。5. 部署与性能优化让系统真正用起来5.1 本地快速启动与局域网访问运行app.py之后默认是监听127.0.0.1的5000端口浏览器输入localhost:5000就能访问。但如果你的用户不在本机比如在同一个局域网的其他机器或者手机上访问就需要让服务监听所有网卡地址。上面我的代码里已经写了host0.0.0.0这样局域网内其他设备通过你的电脑IP加端口号也能访问。首次跑通的时候我记得最容易出问题的是端口占用。5000端口被其他程序占用时Flask会直接启动失败这时候可以换一个端口比如python app.py --port 8080或者干脆在代码里改成port8080。本地调试阶段建议打开debugTrue这样改代码后服务会自动重载还能看到带堆栈信息的报错页面。但生产环境一定记得关闭debug模式和host改成实际监听地址否则存在很大的安全隐患。5.2 模型推理加速的三个实操手段部署之后用户反馈最多的问题就是识别怎么这么慢。我实测下来纯CPU环境下EfficientNetB0推理一张图片大约需要150到300毫秒还没算上图片上传和加载的耗时。如果并发一多Flask默认的单线程模式更会拖慢响应。针对这个问题我做了三个优化效果都很明显第一把Flask切到多线程模式。在app.run里加一个threadedTruePython自带的WSGI服务器就能同时处理多个请求不再串行排队。对于演示项目来说已经是质的变化。第二对模型结果做一次缓存。同一个图片在短时间内被重复上传的概率很低但同一批测试图片经常会被反复点击。我在Flask里加了一个简单的基于文件MD5值的缓存字典相同图片直接返回历史结果省去推理耗时。第三导出一个TensorFlow Lite版本的模型。TFLite模型经过量化后体积从原来的约25MB压缩到8MB推理速度至少翻倍。本地部署时我直接加载量化后的TFLite模型效果几乎没有下降。TensorFlow Lite导出的核心步骤import tensorflow as tf # 加载训练好的模型 model tf.keras.models.load_model(models/best_model.h5) # 转换为TFLite格式 converter tf.lite.TFLiteConverter.from_keras_model(model) converter.optimizations [tf.lite.Optimize.DEFAULT] tflite_model converter.convert() # 保存 with open(models/best_model.tflite, wb) as f: f.write(tflite_model)5.3 向移动端和嵌入式设备延伸如果你想把垃圾分类系统做成一个手机App思路也完全通。把TFLite模型塞进Android项目的assets目录然后用CameraX拍照对照片做相同的预处理后交给TFLite解释器推理。整个流程其实就是这套代码的移动端移植版模型和预处理逻辑完全复用。嵌入式设备上也有一个实际可行的路线用树莓派加摄像头模块在板子上跑TFLite模型通过GPIO控制不同分类对应的垃圾桶指示灯。这个方案的实时性要求不高每两秒识别一次就够用树莓派4B的CPU跑TFLite量化模型完全没有压力我实测单帧推理耗时在100毫秒附近。6. 常见问题与避坑记录6.1 环境配置阶段的高频问题下面这组问题我在开发群和评论区被反复问过整理成速查表方便你快速定位。问题描述可能原因解决方法安装TensorFlow报错找不到匹配版本Python版本过高降到Python 3.9用tf 2.10pip安装超时或慢默认源不稳定使用清华或阿里云pip镜像源import tensorflow报DLL加载失败缺少Microsoft Visual C运行库安装VC Redistributable 2019GPU版本装不上CUDA报错CUDA和cuDNN版本不匹配按官方文档对应版本安装训练时显存不足batch size过大调小batch size到16或86.2 训练过程中的典型问题训练时损失不下降或者验证准确率和训练差太多是最常见的两类问题。前者我一般会排查三步确认数据增强有没有把标签弄乱确认学习率是否调得太小以及确认模型结构里激活函数是否加了正确的位置。后者就是过拟合解决办法通常是增强数据增强强度、增加Dropout比例、或者大幅降低解冻阶段的学习率。我还遇到过一种比较隐蔽的问题验证集的图片是从网上爬的官方图训练集的图片则是摄像头拍的实物图结果验证集准确率虚高但真正用手机拍一张实时照片却频繁识别错误。后来我发现是验证集和训练集同源导致的数据泄露换成摄像头采集的真实照片后准确率才回归真实水平。所以在准备数据集时一定要让模型面对没见过的拍摄环境。6.3 中文标签编码和显示问题Flask框架渲染中文一般没问题但如果你用命令行输出识别结果Windows控制台默认编码是GBKprint中文标签可能报编码错误。解决办法是在代码开头加import sys import io sys.stdout io.TextIOWrapper(sys.stdout.buffer, encodingutf-8)前端页面这边后端返回JSON中的中文需要确保Flask的JSON响应是UTF-8格式。如果浏览器出现乱码在Flask的response对象里手动设置Content-Type为application/json; charsetutf-8即可。6.4 上传文件时被浏览器拦截有一个坑是前端input标签若加了accept属性只允许某些类型的文件有时候用户手机相册里的图片格式是HEIC会被浏览器拦截导致无法上传。我建议对上传文件做服务端校验而不是完全依赖前端过滤这样后端至少能给出一个明确的错误提示而不是卡在浏览器端毫无反应。另外Flask默认的MAX_CONTENT_LENGTH是无限大不设限制的话容易被大图拖垮内存。我加了一个限制app.config[MAX_CONTENT_LENGTH] 8 * 1024 * 1024 # 限制8MB超过限制的图片会返回413错误前端再提示用户压缩一下图片再传。7. 下一步还能怎么扩展这套系统7.1 从单分类到多目标检测目前的垃圾分类系统解决的是一张图片里有一种垃圾的场景但实际生活中的垃圾桶前经常是多个物体混在一起比如一个塑料袋里同时装着果皮和塑料瓶。想处理这种复杂场景就要把系统从图像分类升级为目标检测用YOLO系列的模型来检测图片中每个物体的位置和类别再分别给出处理建议。升级方案我可以给你一个概念上的实现路径用YOLOv8做检测框架准备一个带标注框的垃圾检测数据集训练后每个垃圾物体会被画成框并标出类别。识别结果再叠加四分类投放建议用户拿手机扫一眼所有垃圾都有对应答案体验会比单分类强很多。7.2 增加语音播报和语音交互在Web端做完识别之后你可以用浏览器的Web Speech API直接把识别结果读出来。这个功能在老人使用场景里非常友好识别完后自动播报这是可回收物请投入蓝色垃圾桶比让老人看屏幕上的文字直观得多。语音输入方向也是可以扩展的用户说出电池是什么垃圾通过语音识别解析关键词再调用数据库返回对应分类和投放规则。这个方向本质上是结合了NLP和多轮对话但这个项目目前的主线还是图像识别语音输入可以作为独立功能叠加。7.3 引入大模型做知识库问答如果想做得更智能可以把垃圾分类知识库和大模型API结合起来。用户拍一张照片识别出具体垃圾名称后系统自动去检索这个类别更精细的投放指南比如纸杯子里有剩奶茶到底怎么扔这类常见争议场景大模型可以结合上下文给出更人性化的答复。目前的四分类系统还比较粗细化场景的回答能力是这套系统后续提升空间最大的方向之一。我在实际把垃圾分类系统做到了这一步之后最大的体会是能跑起来和好用之间差着几十个细节。从数据增强到模型量化从中文编码到并发处理每一步都踩过坑也填过坑。希望这篇文章能帮你少走一些弯路。如果你还有更好的分类策略或者部署方案欢迎按你自己的思路继续往下做这套源码的结构改起来相当顺手。本文还有配套的精品资源点击获取