ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

云技术与深度学习驱动的农作物病虫害识别系统部署实战

云技术与深度学习驱动的农作物病虫害识别系统部署实战 简介一套面向毕业设计场景的农作物病虫害识别系统完整源码包基于Python与深度学习技术实现云端识别全流程适合计算机相关专业学生、开发者及农业信息化方向的研究者参考学习。资源共六十个文件压缩包约八十八点七五兆核心包含九份交互式笔记文件覆盖多种主流深度学习框架以及残差网络、视觉几何组网络、稠密连接网络等经典模型实现另有轻量级Web服务端、前端页面、容器化配置与主流云平台部署指南可支撑从模型训练到云端上线的完整链路。资源详细涉及图像数据采集与预处理、卷积神经网络模型训练与优化、云平台服务部署和用户上传界面设计并附带样例图片、说明文档及多种部署配置便于按模块对照学习多份交互式笔记还可横向对比不同网络结构的识别效果配合容器化与部署文档可快速复现实验并迁移到自有云环境。目前已有127人学习下载。1. 基于云技术与深度学习的农作物病虫害识别系统一套能照着复现的毕业设计源码做农作物病虫害识别这个毕设很多同学绕不开这套“基于云技术与深度学习的农作物病虫害识别系统”源码。市面上讲 python 深度学习的资料不少但多数只停留在 notebook 里跑通一个 CNN真正到答辩才发现模型要能部署、接口要能调通、前端要有东西展示才算完整闭环。这个项目的价值在于把整条链路串起来——数据预处理、ResNet50/VGG16 等预训练网络、Flask 推理服务、AWS/GCP 云端部署全部收在一个压缩包。你拿到的不只是训练脚本而是一套能照着复现、扩展、交付的实战源码。它适合正在做毕业设计、课程设计的人也适合想第一次把模型搬到云上的 python 后端开发者。下面按我自己的复现习惯把每个关键环节的参数和踩过的坑逐一拆开讲。2. 读懂仓库再动手从目录坐标拆解训练、服务与部署三段式结构这一章我用“先看目录再跑代码”的思路来拆。解压源码后得到的 Plant_Disease_Detection-master顶层文件看起来很杂但按功能归拢后其实只有三类一是训练 notebook二是 Web 服务与前后端代码三是 Docker 和云平台部署配置。把这三类区分清楚就不会出现“训练完不知道权重存哪更不知道拿它干什么”的尴尬。2.1 文件分类与职责边界先把最显眼的文件依次对号入座训练入口Plant_Disease_RESNET50.ipynb、Plant_Detect_PyTorch.ipynb、Plant_Disease_Detection_TensorFlow.ipynb、Plant_Disease_Detection_Keras.ipynb、Plant_Disease_DenseNet121.ipynb、Plant_Disease_VGG16.ipynb、Plant_Disease_VGG19.ipynb、Plant_Disease_Detection_Fastai.ipynb。Web 骨架app、view、models、static 这四个目录。推理服务server.py。容器与云配置Dockerfile、app.yaml、aws_deployment.md、gcp_deployment.md。辅助资料requirements.txt、README.md、.github/workflows、demo.jpg。这样看训练、服务、部署三条主线都齐了。对刚拿到源码的人我建议只在本地把 notebook 跑通、把权重导出再打开 server.py 确认推理逻辑最后才碰 Docker 和云平台。很多人一开始就想着部署结果云上跑的模型并不知道权重来自本地训练结果——训练没完成其余都是空转。2.2 requirements.txt 里藏着环境选型答案这套源码的依赖相当齐全因为仓库同时给了 PyTorch、TensorFlow、Keras、FastAI 四套 notebook# requirements.txt 核心依赖示例 tensorflow2.10.0 torch1.13 torchvision0.14 keras2.13 flask2.2 django4.1 fastai2.7 Pillow9.0 numpy scikit-learn这里我的建议是不要一次全装。训练主力是 PyTorch就装 torch 和 torchvision打算跟 TensorFlow notebook 走才装 tensorflow 和 keras。我一般在新建的 conda 环境里先装最必需的框架等需要复现另一个 notebook 时再补装对应版本避免 python 环境变成全家桶。CPU 版和 GPU 版框架往往互相干扰这也是最容易踩的环境坑。2.3 正确的运行顺序训练 → 导出权重 → 本地推理 → 容器化这个项目最常见的翻车原因是运行顺序倒过来有人先启动 server.py发现模型加载路径是空。原因很简单源码包里本来就不带训练好的大权重需要训练或直接下载预训练模型来用。我建议按下面顺序执行# 1. 安装依赖 pip install -r requirements.txt # 2. 打开 notebook 训练以 Jupyter 方式启动 jupyter notebook Plant_Disease_RESNET50.ipynb # 3. 训练结束后把模型权重保存到 models 目录 # PyTorch 示例 torch.save(model.state_dict(), models/resnet50_crop_disease.pth) # 4. 启动本地推理服务 python server.py # 5. curl 测试本地接口 curl -X POST -F imagedemo.jpg http://127.0.0.1:5000/predict第一步 pip install 最容易被依赖版本卡住建议在 virtualenv 或 conda 环境里执行不要在系统 python 直接装框架。前三步其实是同一闭环notebook 训练完立即保存权重保存路径要和 server.py 加载路径一致。可以在 server.py 里搜 load_state_dict 或 load_model 确认读取的是哪个文件第四步 server.py 启动后不报“模型文件不存在”就说明路径是对的。2.4 从源码结构反推 Web 端模块边界剩下 view、models、static 是典型的后端 MVC 分层models 包含 Web 层数据模型同时也放训练产物view 负责渲染页面static 放静态资源和上传图片。写论文“系统架构设计”章节时可以直接按这个 MVC 结构画模块图把模型训练和 Web 服务作为两个子系统分开描述。评审问“模型怎么和前端交互”你就说浏览器上传图片 → Flask/Django 接收 → 调用已加载模型推理 → 返回 JSON 给前端展示。这条链路是能在源码里逐行验证的。文件/目录作用典型使用方式*.ipynb模型训练入口Jupyter 中逐 cell 执行models/Web 数据模型与训练产物目录应用层引用app/、view/、static/MVC 后端骨架提供页面与静态资源server.py推理 API 服务python server.py 启动Dockerfile构建镜像docker build -t plant-disease .aws/gcp 部署文档云端部署手册按文档配置环境3. 训练一版真正能用的模型迁移学习与超参数细调3.1 为什么毕设场景选迁移学习最稳种植场景下的病虫害数据集绝大多数是几百到几千张从零训练一个深度卷积神经网络准确率很难过 80%在验证集上抖动还大。迁移学习则是把 ImageNet 上学好的通用特征作为起点在植物叶片图像上做增量训练。小样本下冻结前若干层、只训练分类头效果稳定显存消耗也低。仓库同时给了 ResNet50、VGG16、VGG19、DenseNet121 几个骨干它们的差异可以粗略概括ResNet50 用残差连接缓解加深后的梯度消失在中等规模数据集上最均衡VGG 结构直观但参数量大推理更慢DenseNet 把每层输出都传到后层小数据上往往更容易拿到较高验证准确率。对毕设来说选 ResNet50 最省心因为速度、精度、显存占用都居中如果论文里需要“网络对比实验”再补跑一组 DenseNet121 或 VGG16 即可。3.2 PyTorch 训练核心片段和参数说明以 Plant_Detect_PyTorch.ipynb 为参照关键代码通常是import torch import torch.nn as nn import torchvision.models as models # 加载预训练 ResNet50替换最后一层为适配自身类别数的分类头 model models.resnet50(pretrainedTrue) in_features model.fc.in_features num_classes 15 model.fc nn.Linear(in_features, num_classes) # 冻结主干只训练 fc 层 for name, param in model.named_parameters(): if name.startswith(fc): param.requires_grad True else: param.requires_grad False criterion nn.CrossEntropyLoss() optimizer torch.optim.Adam(model.fc.parameters(), lr0.001) scheduler torch.optim.lr_scheduler.StepLR(optimizer, step_size10, gamma0.5)这段有三个点值得注意。第一pretrainedTrue 是迁移学习的核心预训练权重决定了后续训练的上限。第二num_classes 必须和自己标注类别数一致例如数据集有 38 类病虫害这里要写成 38很多样例 notebook 默认是 15 或 10直接训练会拿错标签。第三先冻结主干只训练 fc 层是为了首轮收敛更快跑 10 个 epoch 后再把最后几个残差块解冻继续微调效果通常更好。训练循环再补一段model.train() for epoch in range(30): running_loss 0.0 for images, labels in train_loader: images, labels images.to(device), labels.to(device) outputs model(images) loss criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() running_loss loss.item() scheduler.step() print(fepoch {epoch1}, loss {running_loss / len(train_loader):.4f})注意 images/labels 都必须在兼容设备上很多新手本地有 CUDA却忘了把模型和数据统一送到 device训练就报错或异常慢。批次大小建议从 16 起步在 224×224 输入下8G 显存基本没问题如果显存紧张就降到 8。3.3 数据预处理与增强参数的具体设置仓库训练数据通常先 resize 到 224×224再做随机翻转、旋转、颜色抖动。这是我强烈不建议省掉的一步from torchvision import transforms transform_train transforms.Compose([ transforms.Resize((224, 224)), transforms.RandomHorizontalFlip(0.5), transforms.RandomRotation(20), transforms.ColorJitter(brightness0.2, contrast0.2), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ])RandomHorizontalFlip(0.5) 是 0.5 概率随机水平翻转对叶片高度对称的目标有效RandomRotation(20) 是最大 20 度旋转模拟拍照角度偏差ColorJitter 里 brightness 和 contrast 调到 0.2提高对光照变化的鲁棒性。Normalize 的 mean/std 必须用 ImageNet 统计值因为预训练模型在这组分布上学忘记这一行会让推理分布偏移识别效果明显变差。3.4 训练中怎么判断没白练最直观的指标是训练损失与验证准确率曲线。训练损失持续下降、验证准确率不涨往往是过拟合两者都不动先检查数据和标签对不对得上再看学习率是不是太大导致震荡。毕设里最常见的假阳性结论是训练集 98%换成实拍图明显下降这里多半是数据增强太弱导致泛化不足。把增强从简单 resizetoTensor 换成上面的方案后验证准确率一般能提升 3 到 5 个点代价是训练时间多出约四分之一。4. 把训练好的模型搬到云端Flask 推理 API、Docker 镜像与云平台部署4.1 用 Flask 把模型封装成在线识别接口源码里的 server.py 相当于整个项目对外提供服务的出入口核心逻辑可以归纳成“接收图片 → 预处理 → 推理 → 返回 JSON”。常见的 Flask 实现from flask import Flask, request, jsonify import torch import torchvision.transforms as transforms from PIL import Image import io app Flask(__name__) device torch.device(cpu) # 服务器没有 GPU 时统一走 CPU 推理 model load_pretrained_model(models/resnet50_crop_disease.pth, device) model.eval() transform transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), transforms.Normalize(mean[0.485, 0.456, 0.406], std[0.229, 0.224, 0.225]) ]) app.route(/predict, methods[POST]) def predict(): file request.files.get(image) if not file: return jsonify({error: no image uploaded}), 400 raw file.read() img Image.open(io.BytesIO(raw)).convert(RGB) tensor transform(img).unsqueeze(0).to(device) with torch.no_grad(): out model(tensor) prob torch.softmax(out, dim1) idx prob.argmax(dim1).item() confidence prob[0][idx].item() return jsonify({label: str(idx), confidence: round(confidence, 4)}) if __name__ __main__: app.run(host0.0.0.0, port5000)这里的 host0.0.0.0 是为了让容器外部和云服务能访问到如果留在 127.0.0.1Docker 端口映射即使配好外部也访问不到。model.eval() 也是最容易漏的一步不然 BN 层和 Dropout 仍然处于训练模式同一张图每次预测结果都可能不同。云端没 GPU 时直接 device torch.device(cpu)不用处理 CUDA 环境代价是单次推理可能到 200 毫秒到 1 秒之间用于毕设完全够。4.2 Dockerfile 配置与构建细节仓库自带 Dockerfile整理出来大致是FROM python:3.9-slim WORKDIR /app COPY requirements.txt . RUN pip install -r requirements.txt COPY . . EXPOSE 5000 CMD [python, server.py]有个很痛的坑python:3.9-slim 这个基础镜像不带 CUDA如果你的 server.py 写了 .cuda()镜像能构建成功启动时却会因找不到 CUDA runtime 直接报错。所以容器内推理我建议强制走 CPU真要 GPU 加速就得换 nvidia/cuda:11.x-runtime 基础镜像并用 nvidia-docker 启动。另外COPY . . 很容易把本地临时文件和模型权重一起打进去镜像超过 2GB拉取和启动都极慢。我通常用 .dockerignore 排除 dataset 和 notebook 里的中间结果。镜像构建和本地验证docker build -t plant-disease:v1 . docker run -d --name plant-api -p 5000:5000 plant-disease:v1 curl -X POST -F imagedemo.jpg http://127.0.0.1:5000/predict-p 5000:5000 是端口映射左 5000 是宿主机端口右 5000 必须和 server.py 里 port5000 对齐。云服务器安全组如果没放行 5000 端口curl 在公网 IP 上访问不通这是云部署最常遇到的外围问题。4.3 云端部署AWS 与 GCP 的核心步骤对照仓库给了 aws_deployment.md 和 gcp_deployment.md 两份文档对比下来两者核心步骤几乎一样区别只在计算实例和安全组规则。步骤AWSGCP准备计算实例EC2 选择机型Compute Engine VM 实例环境准备SSH 登录后安装 docker、python 3.9同左上传代码与权重scp 或 git clonegcloud compute scp构建镜像docker builddocker build运行容器docker run -d -p 5000:5000同左安全组放行 5000 端口EC2 Security Group 入站规则VPC 防火墙规则做毕设从成本考虑单核 2G 内存的机器就能跑 CPU 推理瓶颈只在吞吐量。如果你一定要用 GPU 实例AWS 的 g4dn.xlarge 按小时计费演示几个小时没问题GCP 对应 e2-standard-2 其实也够。注意别把 GPU 实例长期开着不然费用会让项目失去低成本优势。如果你想用更云原生的方式仓库里 app.yaml 可以用在 GCP App Engine 上不过那套配置面向自动扩展答辩现场不适合折腾先用 Docker 跑通最稳妥。5. 常见问题排查与避坑指南5.1 训练过拟合训练准确率 98%验证集却卡在 80%现象是 notebook 前几个 epoch 的 loss 下降很快之后验证集准确率不再提升甚至往回掉。原因是小样本训练时数据增强不足模型把叶片背景和光照当成类别特征记住了。解决思路分三步按 3.3 节的参数加上 RandomRotation 和 ColorJitterepoch 从 30 降到 15配合 EarlyStopping在验证集连续 5 个 epoch 不涨时提前结束在全连接层前增加 Dropout 到 0.5。毕设阶段与其追求训练集 100%不如保证验证集 90% 上下答辩现场演示的正是验证集或现场图片这个数字更能说明问题。5.2 本地推理正常前端上传图片就报 500现象是 curl 直接测接口通了前端上传或换图片格式时接口报错。原因一般有两个一是图片是 4 通道 PNG模型拿到后 shape 不符合二是前端上传字段名和 request.files.get(image) 不一致前端传了名为 file 的字段。解决服务端统一 Image.open(...).convert(RGB)把三通道转换强制写在预处理里字段名写死后由后端日志确认实际收到的 key。还有一种隐蔽情况curl 没问题但浏览器跨域失败因为浏览器预检请求没被允许这时看后端日志和前端请求头确认是否需要放开 CORS。5.3 云端部署后公网 IP 访问超时现象是本地 Docker 容器跑得好好的部署到云后公网 IP:5000 连不上。原因九成是安全组或防火墙没放行端口。AWS 需要给实例关联的安全组增加自定义 TCP 入站规则端口 5000GCP 需要到防火墙页面创建 VPC 防火墙规则方向为入站、协议 tcp:5000。另一种情况是容器根本没起来用 docker ps 看状态再用 docker logs 查看启动日志。我遇到过 EC2 上容器重启后端口被占用的问题排查顺序是先看 docker ps 状态再看 docker logs 报错最后检查安全组规则。5.4 容器里模型权重文件找不到现象是本地 python server.py 正常构建 Docker 后启动报 FileNotFoundError。原因是 Dockerfile 构建上下文没有包含模型权重或者 COPY 时权重被 .dockerignore 排除了。解决把权重放到项目内固定路径构建前用 ls 确认文件在构建上下文里如果权重过大建议用 docker run -v /path/to/weights:/app/models 挂载到容器内。现在我在构建镜像前都会先检查一遍 .dockerignore保证权重文件是干净、可复现的版本。6. 交付与验证让毕设系统在答辩现场不翻车模型训练和云端部署做得再完整最终还是要交付成能被演示、被提问、被验收的成果。这一章分享一套我如今做这类项目都会强制执行的验证流程专治“平时跑得好答辩那天翻车”。用测试集建立一份客观效果报告而不是打印一个 final loss 就结束from sklearn.metrics import classification_report, confusion_matrix model.eval() all_preds, all_labels [], [] with torch.no_grad(): for images, labels in test_loader: outputs model(images.to(device)) _, preds torch.max(outputs, 1) all_preds.extend(preds.cpu().tolist()) all_labels.extend(labels.tolist()) print(classification_report(all_labels, all_preds))classification_report 里的 precision、recall、f1-score 比单一准确率更有说服力尤其在病虫害类别不平衡的项目里。你可以挑两三个效果最好和最差的类别在论文里分析原因评审会认为你做过深入分析。然后是演示素材的准备。把 demo.jpg 换成三组图片真实农田照片、公开数据集典型样本、带背景干扰的难例。每组图片都手动记录期望类别部署后逐个请求接口比对返回的 label 和置信度。如果某张图置信度低于 0.5你可以主动说明“模型泛化仍有局限”这比全程展示完美样例更真实。最后是我的自检清单确认 server.py 用相对路径或明确的绝对路径加载权重确认请求字段名和前端表单名一致检查云服务器安全组已放行 5000 端口测试上传一张超过 2MB 的图片避免 nginx 默认限制卡住请求准备一个模型不可用的友好错误返回而不是让 Flask 吐堆栈。我以前做过一次项目答辩前一晚才发现权重路径写死在本地绝对路径容器里根本找不到。从那以后每次训练完和部署前都强制走一遍上面的清单确保服务器上跑的一定是刚导出的那版模型。做毕设最怕的不是模型不够好而是链路某处悄悄断了却没有及时察觉。这套源码正好就是一个完整的链路标本希望你拿它复现时少走弯路希望帮到你。本文还有配套的精品资源点击获取
返回列表