ARTICLE DETAIL

资讯详情

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

MATLAB+VGG19实现农作物病虫害识别:迁移学习实战指南

MATLAB+VGG19实现农作物病虫害识别:迁移学习实战指南 简介这套以果树病虫害识别为实际场景的深度学习入门实例面向刚开始接触深度学习、希望借助MATLAB工具箱快速上手图像分类任务的开发者也适合作为高校相关课程的综合实训素材。内容以VGG19迁移学习为主线系统讲解数据集如何设置与增强、分类模型如何搭建、训练与测试阶段如何调参与评估并利用多种果树病害图片演示完整的建模流程帮助读者把文档概念真正落到代码中。整个压缩包共935个文件主体是928张果树叶片样本图片另外附带MATLAB脚本、实时脚本、已训练模型、类别标签表格以及说明文本数据、代码、模型和文档一应俱全便于对照学习和二次开发。这些图片覆盖苹果、梨等多种果树的不同病害表现既可用于训练分类器也可用来验证数据增强和迁移学习的效果。包体约为503.61MB容量主要来自高清图像数据但结构化组织让检索和迭代都相对便捷。目前已有2.4万余人学习下载这一资源在实用性和系统性上获得了较多认可适合作为毕业设计、科研预实验或竞赛参赛的起步模板。1. 为什么在MATLAB里用VGG19做病虫害识别很多人一提到深度学习条件反射就是Python加PyTorch。但如果你手里的数据是几千张拍摄条件参差不齐的果树病害照片需要快速迭代模型、观察中间层特征、甚至要把训练好的网络导出到嵌入式设备上MATLAB的Deep Learning Toolbox反而比Python生态更容易把人从环境配置和调试细节里解放出来。这个实例选VGG19作为主干网络原因也简单它虽然结构老、参数多但在中小规模图像分类任务里特征提取能力扎实尤其在农业影像这种背景噪声大的数据上迁移学习启动后的收敛速度比从零训练快得多。适合用这套流程的人有两类一类是刚接触深度学习、想搞清楚数据集组织和训练流程的工程师另一类是已经会跑PyTorch、但需要在MATLAB里完成算法验证和模型导出的研究者。下面按数据准备、模型搭建、训练配置、测试评价四条线拆开讲所有代码以R2022a及以上版本的Deep Learning Toolbox为准。2. 数据集设置imageDatastore标签映射与数据增强2.1 文件命名与目录结构是最容易忽略的起点这个实例给出的图片列表类似“Apple4 (94).jpg”“Apple3 (6).jpg”“Apple2 (23).jpg”看起来杂乱但背后其实是典型的多类别病害数据组织方式。做法是在项目根目录下为每个病害类别建立独立子文件夹文件夹名称就是类别标签。假设你有苹果黑星病、锈病、健康果三类目录结构应当是这样data/ Apple_Scab/ Apple3 (6).jpg Apple4 (94).jpg Apple_Rust/ Apple2 (23).jpg Healthy/ Apple3 (24).jpg注意文件名里的数字序号只是原始采集编号和标签完全没有关系。如果你拿到的是类似本题这样的“Apple4 (55).jpg”混合文件第一步就是用dir遍历、按文件名关键字或人工核对后移动到对应类目下。这一步不做干净后面imageDatastore自动标注的标签就会全是错的。2.2 用imageDatastore加载并划分训练集MATLAB里读取图像数据集的标准入口是imageDatastore它不把图片一次性载入内存而是记录路径并在迭代时按批读取这对大目录很关键。核心代码如下dataFolder ./data; imds imageDatastore(dataFolder, ... IncludeSubfolders, true, ... LabelSource, foldernames); % 划分训练集、验证集、测试集 [imdsTrain, imdsVal, imdsTest] splitEachLabel(imds, 0.7, 0.15, randomized);参数说明IncludeSubfolders必须设为true否则子目录下的图片全部读不到LabelSource设为foldernames表示直接用子文件夹名作为分类标签。splitEachLabel按每个类别分别随机抽取70%作训练、15%作验证、15%作测试randomized保证每类在三个集合中的分布比例一致。划分后建议先看一眼各类别数量countEachLabel(imdsTrain)如果某个类别的样本数只有几十张甚至更少后面训练时这个类的召回率一定会塌需要额外做数据增强或收集样本而不是直接进模型。2.3 数据增强防止过拟合的第一道闸VGG19的输入尺寸固定为224×224而果园里拍的图片分辨率、角度、光照差异很大。直接用imresize硬压缩会丢失大量纹理细节病害病斑本身又是小目标因此增强必须配合缩放来做。常见做法是用imageDataAugmenter定义随机变换再接augmentedImageDatastore统一输出尺寸augmentation imageDataAugmenter( ... RandRotation, [-15 15], ... RandXTranslation, [-10 10], ... RandYTranslation, [-10 10], ... RandXScale, [0.9 1.1], ... RandXReflection, true); augImdsTrain augmentedImageDatastore([224 224], imdsTrain, ... DataAugmentation, augmentation, ... OutputSizeMode, resize);augmentedImageDatastore和imageDatastore的区别在于前者每次读取时都对图像做随机变换并调整到224×224相当于在线增强不占额外磁盘空间OutputSizeMode除了resize还有centercrop如果要保留长宽比信息选centercrop更适合。验证集和测试集不要加随机旋转和翻转否则评测结果不稳定augImdsVal augmentedImageDatastore([224 224], imdsVal, OutputSizeMode, resize); augImdsTest augmentedImageDatastore([224 224], imdsTest, OutputSizeMode, resize);增强参数不是越多越好。RandRotation超过±15度会把苹果果柄、萼洼这些结构信息扭曲掉RandXScale范围过大则会让病斑比例失真模型容易学到形状噪声而不是病理特征。建议先固定旋转和翻转训练一轮看验证集损失再逐步加入平移和缩放。3. VGG19模型搭建迁移学习改层与冻结策略3.1 加载预训练模型与网络结构分析MATLAB加载VGG19不需要手动下载权重文件vgg19函数会自动从Add-On Explorer获取预训练权重需要安装Deep Learning Toolbox Model for VGG19 Network支持包。加载后最重要的动作是可视化分析net vgg19; analyzeNetwork(net)analyzeNetwork会弹出交互式网络图鼠标点任意一层能看到激活尺寸、可学习参数数量、权重维度。对VGG19这种结构重点看两点一是fc6、fc7两个全连接层的输出维度4096二是最后一组卷积层到全连接层之间的drop7层。记下这些层名后面改层时要用。VGG19总共16个卷积层加3个全连接层卷积部分提取的是纹理、边缘、病斑形状等通用视觉特征全连接部分才是针对ImageNet一千万张图学到的类别判别组合。对果树病害这种跟ImageNet类别差异很大的任务保留卷积层、重建全连接层是最合理的迁移策略。3.2 替换分类层从1000类到N类VGG19原始输出是1000类需要把最后三层替换成适配自己类别数的结构。常见做法是直接用layerGraph操作lgraph layerGraph(net); numClasses numel(categories(imdsTrain.Labels)); newLayers [ fullyConnectedLayer(numClasses, Name, fc_new, WeightLearnRateFactor, 10, BiasLearnRateFactor, 10) softmaxLayer(Name, softmax_new) classificationLayer(Name, classoutput_new) ]; lgraph removeLayers(lgraph, {fc8, prob, output}); lgraph addLayers(lgraph, newLayers); lgraph connectLayers(lgraph, drop7, fc_new);WeightLearnRateFactor设为10非常重要新加的全连接层是随机初始化的梯度尺度比预训练层大得多如果不放大学习率训练几十轮后新层还没学明白卷积层的特征也调不动。removeLayers必须一次移除fc8、prob、output三层因为prob依赖fc8的输出output又依赖prob只删一层会留下悬空连接。连接时drop7是VGG19最后一个dropout层的输出它接管了前一层4096维特征。3.3 冻结浅层卷积显存和训练速度的平衡迁移学习里有一个选择是全部层参与微调还是只微调深层、冻结浅层。VGG19前几层卷积学的是颜色、边缘、角点这类通用低级特征在病害图片上依然有效冻结它们可以省下大量反向传播计算量。MATLAB里冻结层的标准做法是借助freezeWeights辅助函数Deep Learning Toolbox官方迁移学习示例自带逐层把WeightLearnRateFactor和BiasLearnRateFactor置为0% 冻结前10层的卷积权重 layers lgraph.Layers; for i 1:10 if isa(layers(i), nnet.cnn.layer.Convolution2DLayer) lgraph replaceLayer(lgraph, layers(i).Name, freezeWeights(layers(i))); end endfreezeWeights返回一个学习率因子为0的同结构层对象replaceLayer按名字替换回网络图。这里要注意冻结不是“不参与前向传播”而是梯度不会回传到这些层前向计算量一点没省省的是显存中的梯度存储和反向传播时间。对一般工程实践样本量在每类500张以下时冻结前5~10层比较稳不容易在浅层产生有害的梯度漂移样本量充足或者病害特征与ImageNet差异极大比如叶片黄化vs.正常绿色的区分时冻结层数可以少一些。4. 模型训练trainingOptions参数调优与收敛监控4.1 trainingOptions各参数对收敛的实际影响训练配置集中在trainingOptions里参数选择直接影响能否收敛和收敛速度。针对VGG19在农业影像数据上的表现推荐从下面这组参数起步options trainingOptions(sgdm, ... MiniBatchSize, 16, ... MaxEpochs, 20, ... InitialLearnRate, 1e-4, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.3, ... LearnRateDropPeriod, 5, ... ValidationData, augImdsVal, ... ValidationFrequency, 30, ... Shuffle, every-epoch, ... Plots, training-progress, ... Verbose, false, ... ExecutionEnvironment, auto);几个关键点的逻辑MiniBatchSize设为16而不是默认的32或128是因为VGG19参数量达到1.4亿每张224×224图像前向反向的显存开销约300MB以上16张一批在单块12GB显卡上比较安全如果你的GPU显存只有8GB降到8。InitialLearnRate用1e-4而不是常见的1e-3原因是预训练卷积层的学习率因子默认为1过大的初始学习率会把微调阶段的权重一步推出原有特征空间。sgdm的动量默认0.9适合这类平滑损失曲面如果换adam初始学习率可以提到5e-4但最终精度往往不如调好的sgdm。4.2 训练中的实时监控与检查点Plots设为training-progress后训练窗口会实时显示训练准确率、验证准确率和损失。判断训练是否健康重点看验证准确率曲线是否平稳上升以及训练损失和验证损失的间距% 每5轮保存一次检查点防止训练中断后从头再来 options.CheckpointPath ./checkpoints; options.CheckpointFrequency 5;CheckpointPath指向的文件夹会自动保存net_checkpoint__*.mat文件里面是训练到当前轮次的网络对象。如果第19轮因为断电中断直接用load取出最近的检查点继续训练即可。验证集上的损失如果在前几个epoch就出现回升说明InitialLearnRate偏大按0.5倍系数逐次下调如果20轮结束后验证准确率还在每轮涨0.5%以上说明没收敛完把MaxEpochs加到30~40再说。训练完成后网络变量就是最终模型trainedNet trainNetwork(augImdsTrain, lgraph, options);这里传入的第一个参数必须是augmentedImageDatastore而不是原始imdsTrainlgraph是我们改完分类层、冻结完浅层后的网络图。整个训练过程如果使用CPUVGG19单轮大约需要20分钟以上建议ExecutionEnvironment保持auto让MATLAB自动优先使用CUDA。5. 模型测试与评价混淆矩阵和单图推理验证5.1 在测试集上计算分类指标训练完成后用classify对测试集做批量预测然后计算混淆矩阵和逐类指标YPred classify(trainedNet, augImdsTest); YTest imdsTest.Labels; accuracy mean(YPred YTest); cm confusionchart(YTest, YPred); cm.Title 果树病虫害识别混淆矩阵;confusionchart会把每一类的精确率、召回率以颜色深浅展示出来对角线越亮说明该类分得越准。如果某两类在混淆矩阵上出现明显的对称误判比如黑星病和锈病互相串不要急着加数据先去看这两类的病斑形态差异是不是真的稳定很多时候是标注本身就有歧义你需要在数据层面重新核对这两类的样本归属。需要数值化指标时用perclassPerformance直接得到每一类的精确率、召回率和F1分数perf perclassPerformance(YTest, YPred);这个函数输出的是表格包含Precision、Recall、F1三列能精确指出是哪一个类拉低了整体准确率。对于农业应用场景召回率比精确率更重要——漏检一个病果比误报一个健康果的代价大得多。所以评价标准应该以各类别召回率的最低值为核心指标而不是只盯整体准确率。5.2 单张图片推理与结果解释测试集指标是宏观评价部署时更常遇到的是“拿来一张新照片判断有没有病”。这里给出单图推理的标准写法img imread(Apple4 (94).jpg); img imresize(img, [224 224]); [label, score] classify(trainedNet, img); [maxScore, idx] max(score); fprintf(预测类别%s置信度%.2f\n, label(idx), maxScore);两点需要注意imresize与训练时的OutputSizeMode要一致训练用的是resize推理也必须用resize否则输入分布的差异会让softmax输出偏乐观score是所有类别的概率向量直接取max就得到置信度。如果最大置信度低于0.6稳妥做法是让算法输出“无法判断”而不是强行给一个低置信度标签。实际部署中我会加一道阈值判断把低于阈值的样本单独收集起来定期回流到训练集里重新标注这样模型的边界能力会越用越准。5.3 导出模型到生产环境的两种路径如果是要把训练好的VGG19部署到实际果园监测设备上MATLAB提供了两条顺手路径。一是导出成ONNX或TensorFlow格式给服务端推理用exportONNXNetwork(trainedNet, fruit_disease.onnx);二是直接生成C推理代码适合嵌入式设备codegen -config:mex -args {coder.typeof(uint8(zeros(224,224,3)))} predictFcn.m注意codegen需要提前把classify封装成一个入口函数输入类型必须明确为uint8的三维数组。这两条路都不需要手动重写网络结构导出的模型结构和训练时完全一致最大限度避免了PyTorch转ONNX常见的算子不兼容问题。这是MATLAB深度学习工具箱在工程落地环节比较突出的一个优势从数据读取、训练到部署全程不需要离开MATLAB环境对以算法验证为主要目标的项目来说省下的时间相当可观。本文还有配套的精品资源点击获取
返回列表