恒美微站 Logo 恒美微站
  • 首页
  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心
  • 联系我们

从迁移学习到Web部署:用Django打造智能垃圾分类系统

  • 首页
  • 资讯中心
  • /
  • 从迁移学习到Web部署:用Django打造智能垃圾分类系统

相关资讯

氛围编程安全实战:六大原则与AI代码审计落地链路 2026/10/7 5:09:16
Loop Engineering实战:用Claude Code、Codex、Cursor搭建AI编程自动闭环 2026/10/7 5:09:16
Python爬虫实战:用requests和lxml抓取全站图书数据 2026/10/7 5:09:16

最新资讯

Type-C、USB-A、Lightning接口针脚定义与协议差异全解析
全彩夜视技术解析:从红外补光到ADAS集成的工程实践
U-Boot移植实战:从DDR初始化到串口调试的完整指南
OpenClaw 应用场景有哪些?从 AI 智能体到自动化任务落地
弃用Trae转投Kiro后,我把AI编程工具对比做成了可复现清单
TPU薄膜供应商怎么选?实战经验谈:参数、验厂与合同避坑

今日推荐

SSD不认盘怎么修?金士顿SV300板级排查与短接ROM进工厂模式
Unity 3D RPG开发:C#状态机与物理更新时机实战指南
AIoT开发工程师岗位全景:从嵌入式Linux到边缘计算与端侧AI部署

本周热门

MR25H40CDF + PIC18F65K40:工业记录仪高可靠存储实战
基于STM32的数控恒压恒流电源设计:从硬件到PID调参全解析
LT9211 MIPI重定时器原理与双路扇出实战指南

本月精选

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证
2026 大模型集体涨价:用 Python 做企业 Token 成本测算与选型避坑(附配置)

从迁移学习到Web部署:用Django打造智能垃圾分类系统

发布时间:2026/10/7 5:09:16
从迁移学习到Web部署:用Django打造智能垃圾分类系统 1. 智能垃圾分类到底该做什么先想清楚系统的核心价值我最早接触这个题目是帮一个师弟做毕业设计。他一开始的想法很直接用摄像头拍垃圾电脑告诉我这是哪一类。但真正动手才发现“垃圾分类系统”这个词听起来简单里面要拆的问题远比想象中多。做一个技术Demo容易做一个真正能用的系统需要考虑的细节非常密集。先说说这个系统到底解决什么问题。垃圾分类的难点其实不在“分类”本身而在“用户不知道手里的垃圾属于哪一类”。我见过太多人站在垃圾桶前面犹豫沾了油的塑料袋算可回收还是其他垃圾奶茶杯到底丢哪里电池分几种这种场景下一个能拍照识别、告诉用户“这是什么东西、应该丢哪个桶”的工具比单纯搞一个炫酷的模型有价值得多。所以这个项目本质上不是一个纯粹的深度学习项目而是“图像识别能力 Web业务系统”的结合。后端负责用户管理、识别记录、知识库查询图像识别负责把照片翻译成垃圾类别。选Django做后端是因为它的MTV架构、ORM、Admin后台、表单处理这些能力能让我用很小的成本把业务逻辑搭起来把精力集中在识别模型的集成和系统体验上。这个选题很适合几类人毕业设计要交差的同学想完整走一遍“模型训练到Web部署”全流程的Python开发者以及想给社区或者校园做一个实际工具的人。2. 图像识别模型的选型思路为什么我选了迁移学习而不是从零训练2.1 从零训练和迁移学习的真实差距很多新手一上来就想自己搭一个CNN网络从零训练垃圾分类模型。这个坑我踩过结果很惨数据集只有几千张图自己搭的网络收敛慢、准确率上不去训练十几个小时loss还在0.8附近徘徊。后来我想明白了一个道理——图像识别领域经过这么多年的积累ImageNet上训练好的模型已经学会了通用的纹理、边缘、形状特征这些底层特征跟识别垃圾是共通的。迁移学习的逻辑其实很简单把别人在千万级图片上学到的特征提取能力搬过来我只训练最后的分类层。这就像你新入职一家公司不需要从认识汉字开始学起直接用已有的读写能力去上手业务就行了。我最终选了MobileNetV2作为骨干网络一个关键原因是它体积小、推理速度快在CPU上跑一张图只需要几十毫秒部署在Django服务里非常合适。2.2 数据集怎么选类别体系决定系统的实用性数据集是垃圾分类这个项目的命脉。目前公开的中文场景数据集主要有华为的垃圾分类数据集约40类、各地政府发布的分类标准数据集以及Kaggle上的一些英文版本。我做的时候用的是自建的数据集把类别控制在20类左右覆盖可回收垃圾、厨余垃圾、有害垃圾和其他垃圾四个大类的常见物品。需要特别强调的是类别体系的设定一定要跟后续的“投放指南”功能联动。如果只是让用户知道“这是塑料瓶”还不够系统还应该告诉用户塑料瓶属于可回收垃圾、需要压扁后再投放这些信息放在数据库里在前端展示时才完整。所以我在设计时把数据集分成了两级物品类别具体是什么和垃圾桶类别该进哪个桶。模型负责识别物品类别业务代码负责映射到投放指南。训练细节可以给一个参考配置。图像统一缩放到224x224做随机水平翻转、随机旋转10度、亮度对比度抖动这些数据增强优化器用Adam学习率初始0.001FC层全部重新训练之前层的权重冻结。大约50个epoch后测试集准确率可以到92%左右对于垃圾分类这种场景已经够用。2.3 模型导出一个常被忽略却又绕不开的环节模型训练完成只是第一步。在Django里使用TensorFlow模型有几种常见做法我用表格整理一下方式适用场景优点缺点直接加载.h5文件快速Demo、开发环境改动少几行代码搞定模型文件大约20MB加载慢转成TensorFlow Lite (.tflite)生产环境、CPU推理体积缩小约75%推理更快需要额外转换步骤某些算子有兼容问题用TensorFlow Serving高并发、模型独立部署接口清晰与业务解耦架构复杂多一个服务要维护我建议开发阶段直接用h5文件跑通流程部署时再转成TF Lite。开发优先追求迭代速度部署优先追求稳定和性能这两件事分开考虑不要在一个阶段同时处理。TFLite转换方法不复杂加载模型后调用tf.lite.TFLiteConverter.from_keras_model()加几行量化配置转换脚本十几行就能搞定。3. Django工程与数据模型设计从ORM表结构到业务闭环3.1 项目结构划分一个app做业务一个app做识别用Django做这类项目最忌讳的就是把所有代码写在一个app里。我前一个版本把视图、模型、工具函数全部堆在views.py里到后面改需求时一团乱麻。重新规划后结构很清晰waste_sorting/ ├── config/ # 项目配置 │ ├── settings.py │ ├── urls.py │ └── wsgi.py ├── apps/ │ ├── users/ # 用户管理 │ ├── recognition/ # 图像识别核心业务 │ └── knowledge/ # 垃圾分类知识库 ├── recognition_engine/ # 模型加载、推理、图像预处理 │ └── classifier.py ├── static/ # 前端静态文件 ├── media/ # 用户上传的图片 └── templates/这里有一个容易被新手忽略的点Django的app之间尽量保持低耦合。recognition负责接收上传、调用推理引擎、保存记录knowledge负责查询投放指南两者通过数据表关联不要互相import对方的视图函数这样后期维护才轻松。另外recognition_engine这个Python包不属于任何app它更像一个独立的服务层专门做模型加载和推理好处是Django的启动、迁移、admin都跟它无关模型坏了不影响整个项目跑起来。3.2 数据表设计识别记录、物品类别和用户之间的关联数据表是整个系统的地基。设计的时候我画过几版关系图最后保留下来的核心表如下# models.py 核心表设计节选 from django.db import models from django.contrib.auth.models import User class WasteCategory(models.Model): 垃圾桶大类可回收、厨余、有害、其他 name models.CharField(max_length50, uniqueTrue) symbol models.CharField(max_length10) # 分类图标标识 description models.TextField() # 分类描述 disposal_tips models.TextField() # 投放指导 class WasteItem(models.Model): 具体物品类别如塑料瓶、香蕉皮 name models.CharField(max_length50) category models.ForeignKey(WasteCategory, on_deletemodels.PROTECT) common_name models.CharField(max_length50) # 别称方便搜索 sort_code models.CharField(max_length20) # 物品编码 class RecognitionRecord(models.Model): 每次识别的历史记录 user models.ForeignKey(User, nullTrue, blankTrue, on_deletemodels.SET_NULL) image models.ImageField(upload_touploads/%Y/%m/%d/) predicted_item models.ForeignKey(WasteItem, on_deletemodels.PROTECT) confidence models.FloatField() # 置信度 is_correct models.BooleanField(nullTrue) # 用户是否标记正确 created_at models.DateTimeField(auto_now_addTrue)这个设计的核心逻辑在于用户上传图片后产生一条识别记录识别结果关联到具体的物品类别比如塑料瓶塑料瓶关联到垃圾桶大类可回收垃圾。这样前端可以同时展示“这是什么”和“应该扔哪”用户反馈也挂在记录上为后续模型迭代收集真实数据。一个小经验is_correct这个字段一开始我没加后来发现特别有价值。识别系统最怕的就是“错误但不自知”让用户在识别结果页点一个“识别正确/不正确”的按钮这些标注数据攒起来是后续优化模型最金贵的资源。就算一时间用不到字段先留着不占多少存储空间。3.3 Admin后台管理数据的高效入口Django自带Admin后台在垃圾分类这个场景里发挥作用很大。垃圾分类的物品类别、投放指南知识库这些内容基本是半结构化数据做系统的人常常需要调整没有后台的话只能写SQL或者跑脚本。注册Admin之后直接在后台增删改查还能批量导入导出。有几个设置值得记一下。list_display里加上识别记录的关键字段物品类别、置信度、时间search_fields按物品名称搜索list_filter按大类过滤。这些配置几乎不花时间但每天维护系统的效率提升非常明显。4. 识别功能与Django的集成方式模型加载、图像预处理和接口设计4.1 模型加载策略一次加载全局复用Django里集成深度学习模型最大的性能陷阱就是“每次请求都加载模型”。我最初为了省事直接在views.py里写model load_model(model.h5)结果第一个请求进来花了2秒后面的请求也卡顿不断。原因很简单加载模型意味着把整个网络结构和权重都读进内存这是一个高成本操作绝对不能在视图函数里反复执行。正确的做法有两种。一种是在AppConfig.ready()里预加载模型把模型实例挂到类属性上另一种是直接用一个模块级别的变量在模块导入时完成加载。我比较推荐第二种逻辑更透明# recognition_engine/classifier.py import tensorflow as tf import numpy as np from PIL import Image _MODEL_PATH recognition_engine/models/waste_mobilenetv2.tflite # 模块导入时创建interpreter全局共用 _interpreter tf.lite.Interpreter(model_path_MODEL_PATH) _interpreter.allocate_tensors() _input_detail _interpreter.get_input_details()[0] _output_detail _interpreter.get_output_details()[0] def predict_image(image_path: str, top_k: int 3): 输入图片路径返回预测结果列表 img Image.open(image_path).convert(RGB) img img.resize((224, 224)) img_array np.array(img, dtypenp.float32) / 255.0 img_array np.expand_dims(img_array, axis0) # 增加batch维度变成(1, 224, 224, 3) _interpreter.set_tensor(_input_detail[index], img_array) _interpreter.invoke() logits _interpreter.get_tensor(_output_detail[index]) probabilities tf.nn.softmax(logits).numpy()[0] top_indices np.argsort(probabilities)[::-1][:top_k] results [(int(i), float(probabilities[i])) for i in top_indices] return results这个模块加载后就常驻内存任何视图调用predict_image都直接走推理路径不再创建模型响应时间能从秒级降到毫秒级。补充一点改用TFLite之后模型文件从20MB缩到5MB左右内存占用也小了很多Django进程部署在2G内存的服务器上毫无压力。4.2 图像预处理的精度问题通道顺序、缩放和归一化图像预处理是最容易出错的地方而且出错了很难察觉——模型不报错但识别结果完全不对。预备训练的模型时要留意训练时用的预处理方式。MobileNetV2这类模型的标准预处理是将图片缩放为224x224像素等比例缩放时注意保持物体不变形像素值归一化到0到1区间即除以255.0通道顺序保持RGBTensorFlow默认输入就是RGB跟OpenCV的BGR要区分开增加batch维度因为模型输入形状通常是(1, 224, 224, 3)还有一个细节很多人不知道如果训练时用了tf.keras.applications.mobilenet_v2.preprocess_input它会做特定方式的归一化channels_first或channels_last有区别但自己定义数据集训练时不一定需要这一步。我在项目里使用的是自己定义的数据集和训练脚本所以统一用/255.0归一化导出模型时标注清楚上线后就不会出现训练和推理不一致的问题。这个细节直接影响准确率值得写进代码注释里。4.3 视图函数与URL路由把识别能力变成可用的接口项目的核心视图是上传图片、返回预测结果。我设计了一个视图来处理两个逻辑GET请求渲染上传页面POST请求接收图片文件调用预测保存记录返回结果页# apps/recognition/views.py import os from django.shortcuts import render, redirect from django.conf import settings from .models import RecognitionRecord, WasteItem from recognition_engine.classifier import predict_image, CATEGORY_INDEX_TO_NAME def upload_and_predict(request): if request.method POST: if request.FILES.get(image) is None: return redirect(recognition:upload) image request.FILES[image] # 安全校验和大小限制 if image.size 5 * 1024 * 1024: return render(request, recognition/error.html, {message: 图片不能超过5MB}) # 保存图片 record RecognitionRecord.objects.create( userrequest.user if request.user.is_authenticated else None, imageimage, predicted_itemNone, confidence0.0, ) # 调用推理引擎 image_path record.image.path results predict_image(image_path) class_index, confidence results[0] item WasteItem.objects.get(sort_codeCATEGORY_INDEX_TO_NAME[class_index]) record.predicted_item item record.confidence confidence record.save() return render(request, recognition/result.html, { record: record, tips: item.category.disposal_tips, }) return render(request, recognition/upload.html)这里面有几个细节值得说一说。第一对上传文件做校验是必须的否则用户传一个大视频或者非图片文件进来模型解析的时候会直接崩溃。用Django的ImageField会自动校验是不是图片但文件大小还是要手动检查。第二保存记录和调用预测的顺序很重要——先保存拿到数据库自动生成的ID和文件路径再去调模型这样即使模型推理失败这条记录也已经存在方便排查。第三模型预测返回的是类别索引需要映射到数据库里的WasteItem记录我建议把这个映射表直接做成一个字典常量避免频繁查库。URL配一个path(upload/, views.upload_and_predict, nameupload)就行前后端不分离的Django项目这种MVT模式最直接也能把精力集中在核心逻辑上。5. 识别准确率和体验的调优从模型层到产品层的双路优化5.1 类别不均衡让模型不再“偏科”垃圾分类数据集天然存在类别不均衡问题。厨余垃圾里的果皮、剩菜占了很大比例而有害垃圾里的纽扣电池、过期药品图片相对少。如果不处理模型会对高频类别过拟合低频类别几乎认不出来。我用的处理方法有两个。第一对样本较少的类别做过采样就是复制图片或者用数据增强多生成变换版本第二在损失函数里按类别数量设置权重让模型对低频类别的预测误差更敏感。比较之后数据增强效果更明显因为单纯复制图片容易过拟合而旋转、翻转、色彩扰动这些变换被模型学到的是不变性特征。还有一个技巧是难例挖掘。训练过程中我记录下模型预测错误的图片路径训练结束后人工看一遍发现不少“难例”其实是因为类别本身长得相似比如“纸巾”和“卫生纸”在很多数据集里就是混在一起的。这时候最有效的做法不是调模型而是调整标签定义把容易混淆的类别合并或者把定义写清楚一些。模型层面的优化解决不了数据本身的问题。5.2 置信度阈值低置信度时的“我不确定”机制垃圾分类跟人脸识别这类场景不太一样用户对错误的容忍度很低——你告诉他把有害垃圾丢进厨余桶后果很严重。所以不能只看Top1准确率还要看预测的可信度。我做了这样的设计当置信度低于0.65时前端不直接展示单一结果而是展示“这个物品可能属于以下两类请人工确认”同时显示相似类别的置信度对比。这样把风险从系统判断转移给用户人工判断体验上显得诚实用户也不会有被坑的感觉。如果置信度高于0.9则直接给出明确的分类指引。这个阈值经过实际测试0.65到0.7之间的区间比较合适太低错过了纠错机会太高又让正常结果变得模棱两可。另外界面上展示置信度本身要谨慎。给普通用户看“置信度0.87345123”是没有意义的更好的方式是语义化——比如“我很有把握”对应0.9以上“我比较确定”对应0.75到0.9“请再确认一下”对应阈值以下。后端返回的概率值到了前端转化成可理解的语气这才是产品思维。5.3 用户反馈闭环真实数据的二次利用前面提到RecognitionRecord表里的is_correct字段是用户反馈闭环的第一个环。具体的做法是在结果页加两个按钮“识别正确”和“识别错误”用户点击后异步提交一个AJAX请求直接更新记录。这个交互不打断用户但对后续模型优化价值巨大。有了这些标注数据可以做几件事定期从错误记录里抽样生成“模型错题集”人工分析错误原因把用户标记为“错误”的图片补充到训练集里迭代训练新模型按时间段统计各类别识别准确率动态调整置信度阈值这个闭环做好之后系统的能力会随着用户使用而不断增强这是一个长期价值。很多毕业设计做到“能识别”就停了但真正让人觉得“专业”的恰恰是这个反馈和迭代机制。6. 项目验证与常见坑我掉进去过的那些坑和最终跑通的经验6.1 模型推理阶段最典型的三个坑坑一图片读取时遇到中文路径。Windows下Django的ImageField.path经常返回带中文的目录名TensorFlow的模型加载接口对中文路径兼容性很差。我一开始在本地跑没注意传到服务器上部署时发现怎么都推理失败后来发现是路径编码问题。解决办法是上传时把文件名重命名成纯英文加时间戳或者先复制到临时目录再读取。坑二模型和业务代码版本不一致。Django项目用git管理数据表迁移和业务逻辑是很清晰的但模型文件是二进制文件容易被人遗忘更新。我试过模型迭代了好几个版本但服务器上还跑着旧模型前端展示的分类类别跟新模型对不上。后来强制约定模型文件放到独立目录命名带日期和准确率标记更新模型时同步更新映射表。坑三并发请求导致的内存溢出。TFLite的interpreter默认不是线程安全的。当多个用户同时上传图片多个线程同时调用interpreter.invoke()时偶尔会出现内存错误。解决办法是在调用推理的入口加一个线程锁虽然会略微降低并发能力但换来的是稳定性。对于垃圾分类这种低频场景完全够用。import threading inference_lock threading.Lock() def safe_predict(image_path: str): with inference_lock: return predict_image(image_path)6.2 部署上线时的性能与安全性设置项目在开发环境跑通和真正部署是两回事。我部署时用的是经典的Django Gunicorn Nginx组合有几个配置值得记录。Nginx负责处理静态文件和媒体文件的请求Gunicorn负责跑Django代码和模型推理worker数量设置为2~4个最合适太多反而会因为模型占内存太大而OOM。settings.py里把DEBUG设为False配置好ALLOWED_HOSTS媒体文件路径跟静态文件分开。上传大图是很常见的操作。手机拍摄的照片动辄3到4MB如果不做处理直接进模型不仅上传慢预处理也要花费更多时间。我在前端做了一步压缩把图片最大边控制在1024像素以内后端再限制文件大小这样即使在弱网环境下整个流程也能顺畅跑下来。还有一个生产环境必须注意的问题数据库连接池和并发。Django默认的数据库连接是“每请求新建”在低并发下没问题并发上来之后会看到很多连接错误。配置一下CONN_MAX_AGE把连接复用周期设置为60秒左右能显著减少数据库压力。6.3 最终验证从数据集准确率到真实场景覆盖项目完成后我做了两层验证。第一层是在测试集上算混淆矩阵观察哪些类别之间互相误判画出可视化图表第二层是模拟真实用户场景拿手机拍了办公室和家里常见的20件垃圾包括揉成团的纸、没喝完的塑料瓶、脏湿的纸巾这类容易被真实场景干扰的物品。结果是干净、完整的物品识别准确率很高但“脏乱差”的真实物品识别率会下降一些这正是收集用户反馈、持续迭代模型的意义所在。做一个智能垃圾分类系统技术栈跨度确实不小从Django的ORM和视图逻辑到TensorFlow的模型训练和推理再到Nginx部署和性能调优每一块单独拿出来都有大量内容。但正是这种全栈式的项目才能真正检验一个开发者的综合能力。我在整个过程中最大的体会是不要想着一步到位先把最小闭环跑通——上传图片、模型识别、展示结果——然后一步步优化。先能跑再跑得好最后跑得快这个顺序不能乱。

关于恒美微站

恒美微站专注于为个体商户、工作室提供极简自助建站服务,让每个人都能轻松拥有专业网站。

快速链接

  • 关于我们
  • 建站服务
  • 主题模板
  • 案例展示
  • 资讯中心

服务项目

  • 可视化建站
  • 拖拽编辑
  • 主题定制
  • SEO 优化
  • 网站托管

联系方式

  • 📍 地址:北京市朝阳区建国路 88 号
  • 📞 电话:400-888-8888
  • ✉️ 邮箱:info@hmyw.cn
  • 🕐 时间:周一至周日 9:00-18:00

© 2024 恒美微站 hmyw.cn 版权所有 | 京 ICP 备 12345678 号