尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MATLAB实现CNN卷积神经网络训练与测试:从数据准备到仿真录像

MATLAB实现CNN卷积神经网络训练与测试:从数据准备到仿真录像 简介面向卷积神经网络初学者的Matlab仿真资源包基于Matlab 2021a平台完整实现CNN的训练与测试可对两类幅值不同的随机序列进行分类识别。资源覆盖数据生成、模型构建、训练与测试全流程适合正在入门深度学习、学习卷积神经网络基本原理或希望快速掌握Matlab深度学习工具箱的读者也便于在此基础上调整网络结构或数据生成方式迁移到其他分类场景中。压缩包内共有3个文件1个CNN核心脚本.m负责数据生成、网络搭建与训练测试全部逻辑1张示意图.jpg用于展示网络结构或分类结果1个操作录像.avi完整记录从打开Matlab、设置路径到运行结束的仿真步骤。包体仅1.88MB轻量便捷解压后即可按录像指引运行。录像特别强调了运行前的关键设置即MATLAB左侧当前文件夹路径必须指向程序所在目录可有效避免因路径错误导致的脚本运行失败这一细节对初学者尤其实用。目前已有1332人学习下载说明该入门示例受到了较多学习者关注。借助这份资料读者不仅能快速复现一个可直接运行的CNN分类实验还能通过操作录像对照每一步配置与输出结果深入理解两类随机序列在CNN中的分类过程从而扎实掌握Matlab环境下卷积神经网络的实现思路并为后续修改参数、扩展应用提供清晰起点。1. CNN卷积神经网络训练和测试matlab仿真到底能帮你解决什么拿到一批图像要在几天内把分类效果做出来给别人看我第一个会打开 matlab 而不是 Python。原因不是谁更厉害而是 CNN 卷积神经网络训练和测试这套流程在 matlab 里可以用十几行代码串起来加载数据、定义网络层、设置训练参数、点一下运行训练曲线和准确率就摆在眼前整个过程还能录成仿真操作录像发给没接触过深度学习的人照着复现。这篇笔记就讲这个方案怎么做从训练集/测试集准备、网络结构搭建、训练参数配置到测试评估和录像交付。适合做课程设计、毕业设计以及想快速验证图像分类想法、不想折腾编译环境的工程师。这里不比较框架优劣只讲 matlab 里最顺的一条路以及那些会让你翻车的细节。2. 先搭仿真框架再写代码CNN 在 matlab 里的数据流与工具箱选型很多人第一次在 matlab 里跑 CNN是照着网上的代码粘贴跑通了也不知道为什么。我建议反过来先搞清楚训练和测试这两个阶段各自消费什么、产出什么再动手写。训练阶段输入的是带标签的图像和网络结构输出是训练好的网络参数测试阶段输入的是没参与训练的图像输出是预测标签和真实标签比对得出准确率。搞清楚这条主线后面所有代码都能对号入座。2.1 CNN 在 matlab 里仿真的完整数据流matlab 里一次标准的 CNN 训练-测试流程是这样的原始图像进入imageDatastore或内存数组按 8:2 或 7:3 划成训练集和测试集训练集经过数据增强可选后送入trainNetwork函数内部按你给的layers结构做前向传播和反向传播训练结束后得到一个SeriesNetwork或DAGNetwork对象测试阶段用classify对测试集逐批预测再和真实标签做比对。我把这个流程用文字画出来你写代码前先在心里过一遍图像文件夹或内存数组 ↓ imageDatastore自动读取 打标签 ↓ splitEachLabel按比例切分 ↓ 训练集 --(可选)-- augmentedImageDatastore ↓ trainNetwork(net, layers, options) ↓ 训练好的网络对象 netTrained ↓ classify(netTrained, imdsTest) → 预测标签 ↓ 与真实标签比对 → 准确率 / 混淆矩阵这里最容易被新手忽略的是classify的输入尺寸必须和训练时imageInputLayer里写的一致。比如输入层是[28 28 1]测试图片如果是 32×32 或彩色图classify直接报维度错误。我一般会在数据准备阶段用augmentedImageDatastore或imresize把所有图统一到同一个尺寸而不是在训练完之后才处理。2.2 Deep Learning Toolbox 选型够用在哪不够用在哪做这个仿真只需要 MATLAB 的 Deep Learning Toolbox旧版本叫 Neural Network Toolbox。它负责网络层定义、训练、预测这三件事核心函数就四个imageInputLayer、trainingOptions、trainNetwork、classify。如果装了 Parallel Computing Toolbox训练时能自动用多核 CPU 或 NVIDIA GPU 加速没装也不影响跑通只是慢一些。我在多个 matlab 版本上做过同样的事结论是R2019a 之后的版本对Padding,same、batchNormalizationLayer、confusionchart这些新接口支持得比较稳定建议直接用这些写法别用老版本的pad参数和plotconfusion。老接口不是不能用而是报错信息不直观新手排错成本高。边界也要说清楚matlab 适合快速验证标准 CNN 结构卷积、池化、全连接、残差块适合教学演示和课程设计但它不是让你做前沿研究的地方。想自定义一个很奇怪的算子、想做分布式大规模训练、想无缝部署到移动端PyTorch/TensorFlow 生态更合适。选择 matlab 的唯一理由就应该是“快”和“可视化直观”而不是“功能全”。2.3 让仿真可复现随机种子、脚本化与留痕CNN 训练有大量随机性权重初始化、数据打乱顺序、数据增强的随机变换。同一个脚本上午跑和下午跑准确率可能差 0.5 到 1 个百分点。如果是做课程设计或给评审看这个波动会让人说不清。我一般会在脚本开头固定随机种子% 固定随机种子保证每次训练的可复现性 rng(0);这里rng(0)的作用是把全局随机数生成器重置到一个确定状态。注意它影响的是权重初始化和Shuffle的随机顺序但不影响 GPU 上的某些算子比如 cuDNN 里的卷积算法选择所以在 GPU 上训练时完全复现仍然不保证在 CPU 上基本可以。给评审演示时我建议直接用 CPU 训练结果稳定GPU 训练虽然快但两次结果可能有细微差异。另一个习惯是不要用clear all之外的脏环境跑实验。整个训练-测试过程写成一个.m脚本从rng到confusionchart一条龙下来中途不依赖工作区里残留的变量。这样录像也好录——把脚本从头到尾运行一遍就是完整演示。3. 准备训练集和测试集从 matlab 内置数据到自备图片文件夹数据准备是 CNN 训练里最枯燥但最决定成败的一步。标签和图像对不上、类别顺序不统一、训练测试数据重叠这些错误在训练时才暴露而且报错信息往往和真正的原因毫无关系。所以这一章先把数据这块做实。3.1 最快跑通方案matlab 自带的手写数字集如果你只是想验证“CNN 在 matlab 里能跑通”这件事不要先去找数据集直接用 matlab 自带的手写数字数据。这个数据集一共 5000 张 28×28 的灰度图内容是 0 到 9 的手写数字已经按列排好。加载方式如下% 加载 matlab 内置手写数字数据集 load digits.mat % 数据集划分前 4000 张做训练集后 1000 张做测试集 XTrain X(:,:,1:4000); YTrain categorical(Y(1:4000)); XTest X(:,:,4001:end); YTest categorical(Y(4001:end)); % 看一下数据形状和类别分布 disp(size(XTrain)); % 期望看到 28 28 4000 disp(countcats(YTrain));代码逻辑说明digits.mat里有两个变量X是 28×28×5000 的 uint8 数组Y是 5000×1 的 double 数组。X(:,:,1:4000)把前 4000 张图取出来第三维是样本维。categorical(Y(1:4000))把数字标签转成分类数组这是trainNetwork要求的标签格式。参数说明这里没有硬性规定 4000/1000 的切分比例但 8:2 是常见做法。如果你的样本总数很少比如几百张建议加大训练比例到 0.9否则测试集太小评估结果不稳定。注意categorical如果不手动指定类别顺序它会按数字大小自动排序正好是 0 到 9对数字识别没问题后面遇到自备数据时要自己检查类别顺序。这个内置数据集的优点是零下载、零预处理load进来就能训练。缺点是图像太干净和真实场景差距大跑出来的准确率会虚高通常在 98% 以上。所以它只配用来验证流程不适合写进项目结论。3.2 自备图片数据imageDatastore 自动打标签实际项目里你会面对一整个文件夹的图片比如按类别分子文件夹存放。这时候千万别自己写循环读图matlab 的imageDatastore就是干这个的% 假设 images 目录下有 cat/ 和 dog/ 两个子文件夹 imds imageDatastore(fullfile(pwd, images), ... IncludeSubfolders, true, ... LabelSource, foldernames); % 查看自动生成的标签 disp(imds.Labels); countEachLabel(imds)参数说明IncludeSubfolders, true让 datastore 递归读取子文件夹LabelSource, foldernames表示用子文件夹的名字作为类别标签这是最不容易出错的打标签方式。比手动写一个 CSV 映射稳妥得多——只要你的文件夹结构是规范的标签一定不会错位。countEachLabel用来检查每个类别的样本数。这一步非常关键如果某个类只有十几张而另一个类有几千张CNN 训练出来的模型会对样本多的类严重偏置。常见做法是通过splitEachLabel按比例切分训练集和测试集同时保持每个类别的比例一致% 按标签分层切分每个类取 80% 做训练集20% 做测试集 [imdsTrain, imdsTest] splitEachLabel(imds, 0.8, randomized);randomized参数让切分前先随机打乱避免某个类别的图片在文件夹里按时间顺序排列导致训练集和测试集分布不一致。我踩过这个坑某个数据集按拍摄日期排序前 80% 全是晴天后 20% 全是阴天结果训练集准确率 99%测试集只有 70%。这就是分布不一致。加了randomized之后这个问题基本消失。3.3 数据增强要不要开imageDataAugmenter 的正确用法当训练集样本很少比如每类只有几十张时CNN 很容易过拟合训练损失很低但测试准确率上不去。一个有效的补救手段是数据增强——在训练过程中对每批图片做随机平移、旋转、缩放相当于免费扩充训练集。% 定义数据增强随机平移 ±5 像素随机旋转 ±10 度 augmenter imageDataAugmenter( ... RandXTranslation, [-5 5], ... RandYTranslation, [-5 5], ... RandRotation, [-10 10]); % 包装训练集并统一输出尺寸为 [28 28] augImdsTrain augmentedImageDatastore([28 28], imdsTrain, ... DataAugmentation, augmenter, OutputDataType, single);逻辑说明augmentedImageDatastore的第一参数是输出图像尺寸这里把训练图统一成 28×28正好匹配后面网络的输入层。OutputDataType,single把图像转成 single 精度省内存且和 matlab 默认训练精度一致。参数说明数据增强的幅度要克制。数字识别这类轻度任务平移 5 个像素、旋转 10 度就够了旋转 30 度以上反而会生成不自然的样本拉低准确率。另外注意增强只应该施加在训练集上测试集必须保持原图。如果对测试集也做随机变换评估结果就是靠运气没有意义。还有一点很多人忽略augmentedImageDatastore在每次迭代时会重新生成随机变换参数所以你没法像普通数组那样精确复现某一批数据。这是数据增强的固有特性接受它用第 2 章说的rng(0)控制整体随机性即可。4. 搭网络、配参数、跑训练CNN 在 matlab 里收敛的最小配置数据准备好之后第二步是搭一个能收敛的网络。CNN 结构设计在 matlab 里非常直白每一层做什么都由函数名说明但这不代表你可以随便堆层。我见过不少人套用 ResNet 级别的结构跑 28×28 的小图训练时间翻了几倍准确率反而没提升。对小尺寸图像一个 3 层左右的卷积网络通常就够。4.1 一个经典且能收敛的 CNN 结构下面这段代码是一个适合灰度数字识别的 CNN 结构全部用 matlab 自带层拼出来% 定义网络层结构 layers [ imageInputLayer([28 28 1], Name, input) convolution2dLayer(3, 8, Padding, same, Name, conv1) batchNormalizationLayer(Name, bn1) reluLayer(Name, relu1) maxPooling2dLayer(2, Stride, 2, Name, pool1) convolution2dLayer(3, 16, Padding, same, Name, conv2) batchNormalizationLayer(Name, bn2) reluLayer(Name, relu2) fullyConnectedLayer(10, Name, fc) softmaxLayer(Name, softmax) classificationLayer(Name, output)];逐层说明imageInputLayer([28 28 1])声明输入是 28×28 单通道灰度图convolution2dLayer(3, 8)是 3×3 卷积核、输出 8 个特征图Padding,same保证卷积不缩小尺寸batchNormalizationLayer对每批数据做归一化能显著加速收敛特别是学习率偏大的时候reluLayer是激活函数maxPooling2dLayer(2,Stride,2)把 28×28 下采样到 14×14第二组卷积输出 16 个特征图fullyConnectedLayer(10)输出 10 个类别得分最后softmaxLayer把得分转成概率classificationLayer负责计算分类损失。参数建议fullyConnectedLayer的输出维度必须和类别数一致。很多报错“输出层类别数不匹配”就是因为这里少写或多写了数字。如果你有 5 个类别这里就是fullyConnectedLayer(5)。判断类别数用numel(unique(imdsTrain.Labels))最保险不要手数。4.2 trainingOptions 里每个参数都意味着什么网络结构定了训练怎么跑由trainingOptions控制。给新手一个可以直接抄的配置% 配置训练参数 options trainingOptions(sgdm, ... MaxEpochs, 15, ... InitialLearnRate, 0.01, ... MiniBatchSize, 128, ... Shuffle, every-epoch, ... Plots, training-progress, ... Verbose, true);逻辑说明sgdm指带动量的随机梯度下降是图像分类最稳妥的优化器MaxEpochs,15表示整个训练集被完整遍历 15 遍InitialLearnRate,0.01是初始学习率MiniBatchSize,128是每批喂入网络的样本数Plots,training-progress会在训练时弹出一个实时曲线窗口这是 matlab 仿真最直观的卖点。学习率是最值得花时间调的参数。0.01 适合中等复杂度的小数据集如果损失曲线震荡剧烈降到 0.001如果曲线平滑但下降太慢可以升到 0.03。MiniBatchSize受内存限制CPU 训练不建议超过 256GPU 可以到 128 或 256。Shuffle,every-epoch让每个 epoch 都重新打乱样本顺序防止模型记住固定批次顺序。另外两个不在这段代码里但很常用ValidationData可以在每轮训练结束时自动评估验证集并显示在训练曲线上Verbose,false可以关掉命令行刷屏只留曲线窗口。我一般训练初期开Verbose看每个 iteration 的损失确认数值在下降后再关掉重跑一遍做正式训练。4.3 训练曲线怎么看收敛、过拟合和震荡训练开始后曲线窗口里会有一条损失曲线和一条准确率曲线横轴是 iteration 而不是 epoch。看曲线只需要回答三个问题。第一有没有收敛。正常情况是损失从高到低平滑下降准确率从低到高上升最后趋于平缓。如果准确率曲线是一条几乎水平的直线检查数据标签是否错位。第二有没有过拟合。表现为训练损失持续下降、训练准确率接近 100%但验证准确率如果配置了或测试准确率落后一大截。解决办法是数据增强、在fullyConnectedLayer之前加一个dropoutLayer(0.5)或者减小网络规模。第三有没有震荡。损失曲线像锯齿一样上下跳动通常是学习率偏大。把InitialLearnRate从 0.01 降到 0.001或者改用更小的MiniBatchSize。还有一种情况是训练数据类别不均衡小类别样本的 loss 波动会比较大优先通过splitEachLabel或加权采样解决。如果你用的是 CPU训练速度慢非常正常。15 个 epoch、4000 张 28×28 灰度图几分钟内能跑完如果换成 256×256 彩色图且网络更深CPU 可能要几小时。这时候要么减MaxEpochs要么上 GPU。GPU 不需要额外改代码matlab 自动检测并调用 NVIDIA 显卡前提是装了 Parallel Computing Toolbox 且驱动支持。5. CNN 仿真避坑指南训练和测试中的 5 个翻车现场这一章把我在 matlab 里跑 CNN 遇到过的典型问题整理出来。每一条都是真实发生过的照着检查能省很多时间。5.1 准确率卡在 10% 左右和瞎猜一样现象描述训练损失没有明显下降准确率曲线在 10% 附近浮动。10 分类任务里随机猜就是 10%模型根本没学到东西。原因分析最常见原因是学习率不合适过大或过小都会导致不收敛其次是标签和数据错位尤其是自己写循环读图时下标对不上还有一个隐蔽原因是数据没有归一化输入像素值范围差异巨大导致梯度异常。解决办法先打印几组训练图像和对应标签肉眼确认对应关系再用rng固定种子重跑最后把学习率改成 0.001 或 0.0001 对比一下。如果还是 10%把网络简化到只有一个卷积层排除结构问题。5.2 训练曲线震荡剧烈损失不降反升现象描述损失曲线大幅上下跳动甚至在某个 iteration 后突然冲高。原因分析InitialLearnRate太大梯度更新越过最优区域数据增强幅度过大生成了过于难识别的样本标签噪声也会造成类似现象。解决办法学习率降到 0.001 或 0.0001损失曲线通常会瞬间平稳同时把数据增强的旋转角度从 ±30 度缩到 ±5 度。这两条改完大部分震荡问题都能解决。5.3 训练损失很低测试准确率却上不去现象描述训练准确率冲到 99%训练损失接近 0但测试准确率只有 70% 到 80%。原因分析过拟合模型把训练数据里的细节背下来了包括噪声。解决办法给网络加dropoutLayer(0.5)放在全连接层之前开启数据增强把网络精简减少卷积核数量。这里要注意加上 dropout 后训练损失不再逼近 0这是正常的不要因此误判为结构有问题。5.4 训练或测试时 matlab 报内存不足现象描述训练过程中弹出“Out of Memory”错误Simulink 或 MATLAB 主界面卡死。原因分析MiniBatchSize太大或输入图像尺寸太大导致每批数据在内存和 GPU 显存中的占用超过上限。解决办法先降MiniBatchSize到 32 或 16把imageInputLayer里的图像尺寸改小比如从 224×224 降到 128×128然后用augmentedImageDatastore统一缩放如果你在 GPU 上训练可以在命令行用gpuDevice查看显存占用确认是否被其他进程占用。5.5 classify 报维度错误或类别不匹配现象描述训练正常结束但在测试集上调用classify时提示输入尺寸不符或者混淆矩阵里类别顺序对不上。原因分析测试图像尺寸与imageInputLayer不一致训练集和测试集类别集合不同比如训练时只有 8 类测试数据里忽然出现第 9 类categorical的类别顺序不统一。解决办法测试前用augmentedImageDatastore统一输出尺寸不开启数据增强用categories(imdsTrain.Labels)和categories(imdsTest.Labels)对比两个集合是否一致如果发现测试集有训练集没有的类别回到数据切分那一步仔细看splitEachLabel的结果。稳妥做法是切分前对整个数据集做一次类别统计确保每个类都有足够样本进入训练集。6. 测试评估与仿真操作录像交付一份能照着复现的完整演示模型训练完不算交付把准确率测出来、把过程录下来、让没跑过的人能复现才算完整。这一章是实战收尾也是标题里“含仿真操作录像”这个承诺的落地方法。6.1 在测试集上算准确率、画混淆矩阵训练得到的net是SeriesNetwork对象测试时直接用classify预测所有测试集图片然后和真实标签比对% 预测测试集标签 YPred classify(net, imdsTest); % 计算准确率 accuracy sum(YPred imdsTest.Labels) / numel(imdsTest.Labels); fprintf(测试集准确率: %.2f%%\n, accuracy * 100); % 画混淆矩阵 confusionchart(imdsTest.Labels, YPred);代码逻辑说明classify返回的是一个 categorical 数组长度和imdsTest的样本数一致。YPred imdsTest.Labels逐元素比较预测和真实标签sum统计正确个数除以总数得到准确率。confusionchart是 R2018b 之后推荐的混淆矩阵函数旧版本的plotconfusion也可以但交互性差一些。如果你的测试集有 1000 张图classify会在内部自动分批计算不需要手动切块。如果测试集特别大比如几万张建议用MiniBatchSize参数控制classify(net, imdsTest, MiniBatchSize, 128)可以避免一次加载过多数据导致内存不足。混淆矩阵是给外行看的重点。对角线颜色越深说明分类越准某一行非对角线有明显亮块说明这一类图像经常被认错成另一类这种错误往住源于两类图像外观相似比如手写数字 4 和 9。如果做的是二分类还可以用perfcurve画 ROC 曲线并计算 AUC这部分内容常用于论文和答辩属于加分项。6.2 仿真操作录像录制前的准备和录制顺序第一次给别人演示 matlab 跑 CNN 时我试图用 MATLAB 的record函数录操作过程录完才发现它只能记命令窗口的文本输出根本录不了界面和曲线窗口。这个函数叫这个名字容易误导人千万分清屏幕操作录像还是靠系统级录屏工具。Windows 上按Win G打开 Xbox Game Bar 就能录屏幕指定区域想输出 GIF 用 ScreenToGif要更专业的用 OBS Studio。这些工具都是现成的不需要额外配置。真正值得花心思的是录制顺序。我一般按以下顺序录这段录像基本就是整个项目的操作说明书1. 打开脚本文件和训练数据文件夹展示目录结构 2. 运行数据加载部分展示训练集/测试集划分结果 3. 运行网络结构定义展示每一层的参数 4. 运行 trainNetwork等待训练曲线出现并走完几个 epoch 5. 展示最终的损失和准确率曲线 6. 运行 classify 和 accuracy 计算打印测试集准确率 7. 展示混淆矩阵指出最容易混淆的两个类别 8. 结束前回到代码指出三个最关键的参数位置录制时有一个值得注意的细节训练曲线窗口里横轴是 iteration不是 epoch。外行看录像时会数 15 个 epoch 但发现曲线只走了几百个 iteration以为没跑完。我一般会在录像里补一句说明“每个 epoch 包含 32 个 iteration 左右所以总 iteration 数大约是 epoch 数乘以每个 epoch 的批次数。”这句话能避免一大半疑惑。还有一个多年形成的习惯只要是要交给别人看的仿真我都先固定rng关掉Verbose再录。不然录像里命令行刷屏太快不仅观感差还会掩盖训练进度信息。训练曲线的截图我也会单独存一份和脚本放在同一个目录方便后续写报告直接引用。至于录像的时长我建议控制在 5 到 10 分钟重点录完整流程而不是每个细节都展开。因为真正需要照着复现的人会自己暂停录像去看代码录像的作用是让人相信“这整套东西确实能跑通、确实能得到图上的结果”。最后说句实在话matlab 跑 CNN 最大的价值不是训练出多牛的模型而是用一张训练曲线、一张混淆矩阵、一段操作录像把深度学习的完整链路讲清楚。我自己做课程设计时就是这样交的作业——代码能跑、参数能调、过程能复现、结果能解释。希望这篇笔记能帮你在仿真路上少走几步弯路把时间花在真正需要思考的结构设计和结果分析上。本文还有配套的精品资源点击获取
返回列表