资讯动态

Matlab物体分类实战:VggNet与ResNet对比及迁移学习避坑指南

发布时间:2026/10/25 12:43:40 来源:尧图企业网站定制
简介这份资源围绕VggNet与ResNet两种经典卷积神经网络在物体分类识别中的应用展开面向具备一定深度学习基础、希望借助Matlab动手实践图像分类的学生与研究人员。包内共60012个文件以60002个png图像样本为主辅以4个m脚本、3个mat权重与数据文件、1个pdf说明文档及fig、jpg等辅助文件压缩包约398.58MB可支撑从数据读取、模型搭建到结果可视化的完整流程。内容涵盖两种网络的结构对比、物体识别性能评估、参数初始化与优化器选择等训练策略并给出Matlab环境下的前向与反向传播实现思路便于读者理解残差连接与深层卷积的差异。已有759人学习下载适合作为课程设计、毕业设计或计算机视觉入门项目的参考帮助读者把网络原理快速转化为可运行的分类实验。1. 从一份 VggNet 与 ResNet 的 Matlab 物体分类代码说起如果你手上正好有一份「基于VggNet网络与ResNet神经网络的物体分类识别研究-附Matlab代码.zip」大概率会先卡在同一个地方解压之后一堆 .m 文件和 .mat 文件不知道从哪跑起更不知道 VggNet 和 ResNet 这两个网络到底谁该上场。物体分类识别这件事本身不新鲜但把 VggNet 和 ResNet 放在同一套 Matlab 流程里做对比才是这份代码真正的价值点——它想回答的是「同样一批图片深网络和更深网络差在哪」。这篇笔记面向三类人正在做 matlab图像处理大作业的学生、想用 matlab 快速验证卷积神经网络效果但不想碰 Python 环境的工程师、以及需要给物体分类识别任务做基线对比的人。我会把 VggNet 与 ResNet 的结构差异、Matlab 里的加载与训练路径、参数怎么调、以及最容易翻车的几个点讲清楚让你拿到代码后能真正跑通而不是停在「能打开」这一步。2. VggNet 与 ResNet 在物体分类任务里的结构差异与选型2.1 VggNet 的堆叠逻辑为什么在 Matlab 里好复现VggNet 的核心思路非常朴素全部用 3×3 小卷积核靠不断堆叠来加深网络。它的经典配置是 5 个卷积块每块后面接最大池化通道数从 64 一路翻到 512最后接三层全连接做分类。这种「一路直筒」的结构在 Matlab 里特别好写因为 Deep Learning Toolbox 提供的convolution2dLayer、maxPooling2dLayer、fullyConnectedLayer可以逐层拼出来不需要处理跨层连接。从物体分类识别的角度看VggNet 的优势是特征提取层次清晰浅层抓边缘和纹理深层抓部件和整体形状。缺点是参数量巨大Vgg16 大约 1.38 亿参数其中绝大部分集中在全连接层。这意味着在 Matlab 里如果直接用 CPU 训练基本等于自虐即便用 GPUbatch size 也上不去。我一般会这样判断如果你的数据集是几百到几千张的小规模物体图片且显存有限VggNet 更适合做特征提取器而不是端到端微调。把fc7层的输出当作特征向量再送进 SVM 或简单的全连接分类头往往比硬训整个网络更稳。2.2 ResNet 的残差连接解决了什么实际问题ResNet 要解决的是「网络越深反而越差」这个反直觉现象。理论上网络越深表达能力越强但实际训练中梯度在反向传播时会衰减导致浅层几乎学不到东西。残差连接的做法是让某一层的输出变成F(x) x其中x是恒等映射。这样梯度可以沿着 shortcut 直接回传深层网络的训练难度大幅下降。在物体分类识别任务里ResNet 的残差块让网络可以做到 50 层、101 层甚至更深同时保持可训练性。Matlab 里可以用additionLayer配合convolution2dLayer手动搭残差块也可以直接调用预训练模型。常见做法是加载resnet50或resnet18替换最后的全连接层和分类层然后在新数据集上微调。这里有个选型上的血泪经验不要因为 ResNet 更深就无脑选它。如果你的物体类别只有 5 到 10 类图片分辨率也不高ResNet50 的参数量反而容易过拟合。ResNet18 或者 VggNet 做特征提取加浅层分类器效果可能更稳。2.3 两个网络在 Matlab 中的加载方式对比Matlab 对预训练模型的支持主要通过Deep Learning Toolbox Model for ResNet-18 Network这类支持包实现。安装之后可以直接用resnet18、resnet50、vgg16、vgg19这些函数拿到网络对象。下面这段代码展示了两者的加载和输入层查看方式% 加载预训练的 VggNet 和 ResNet netVgg vgg16; % 需要安装 VggNet 支持包 netRes resnet50; % 需要安装 ResNet-50 支持包 % 查看输入层要求 inputSizeVgg netVgg.Layers(1).InputSize; % 通常为 [224 224 3] inputSizeRes netRes.Layers(1).InputSize; % 通常为 [224 224 3] % 查看最后几层确认分类层结构 disp(netVgg.Layers(end-2:end)); disp(netRes.Layers(end-2:end));逻辑说明vgg16和resnet50返回的是DAGNetwork或SeriesNetwork对象输入尺寸默认都是 224×224×3。参数上要注意如果你的物体图片不是这个尺寸必须在数据预处理阶段统一 resize否则前向传播会直接报维度错误。最后几层通常是全连接层、softmax 层和分类层微调时就是替换这几层。提示如果vgg16或resnet50报未定义先检查支持包是否安装完整。Matlab 的附加功能管理器里搜「Deep Learning Toolbox Model」就能找到对应支持包。3. 用 Matlab 跑通物体分类识别的最小流程3.1 数据准备与 imds 的四个关键设置Matlab 处理图像分类最顺手的方式是imageDatastore。它不需要你把图片整理成特定格式只要按类别分文件夹存放即可。假设你的物体图片目录结构是data/train/猫/xxx.jpg、data/train/狗/xxx.jpg那么% 创建图像数据存储 imds imageDatastore(data/train, ... IncludeSubfolders, true, ... LabelSource, foldernames); % 查看类别分布 labelCount countEachLabel(imds); disp(labelCount); % 按比例划分训练集和验证集 [imdsTrain, imdsVal] splitEachLabel(imds, 0.8, randomized);逻辑说明IncludeSubfolders设为 true 才能递归读取子文件夹LabelSource设为foldernames后Matlab 会自动把文件夹名当作类别标签。splitEachLabel的第二个参数 0.8 表示每个类别取 80% 做训练剩下 20% 做验证。参数上要注意如果某些类别样本特别少splitEachLabel可能会让验证集里没有该类样本这时候需要手动检查imdsVal.Labels的分布。3.2 替换最后三层完成迁移学习预训练模型是在 ImageNet 1000 类上训练的你的物体分类任务类别数几乎不可能正好是 1000。所以必须替换最后的全连接层、softmax 层和分类层。以 ResNet50 为例% 加载预训练网络 net resnet50; % 获取类别数 numClasses numel(categories(imdsTrain.Labels)); % 替换最后三层 lgraph layerGraph(net); newLayers [ fullyConnectedLayer(numClasses, Name, new_fc, ... WeightLearnRateFactor, 10, BiasLearnRateFactor, 10) softmaxLayer(Name, new_softmax) classificationLayer(Name, new_classoutput)]; lgraph replaceLayer(lgraph, fc1000, newLayers(1)); lgraph replaceLayer(lgraph, fc1000_softmax, newLayers(2)); lgraph replaceLayer(lgraph, ClassificationLayer_fc1000, newLayers(3));逻辑说明WeightLearnRateFactor和BiasLearnRateFactor设为 10意思是新加的全连接层学习率是其他层的 10 倍。这是因为预训练层的特征已经很好不需要大改而新层是随机初始化的需要快速收敛。replaceLayer的三个层名必须和原网络中的层名完全一致不同版本的 Matlab 支持包里层名可能略有差异可以用net.Layers(end-2:end).Name先查一下。3.3 训练参数怎么设才不翻车训练选项用trainingOptions配置。下面是一组我常用的参数options trainingOptions(sgdm, ... MiniBatchSize, 16, ... MaxEpochs, 12, ... InitialLearnRate, 1e-4, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.1, ... LearnRateDropPeriod, 5, ... Shuffle, every-epoch, ... ValidationData, imdsVal, ... ValidationFrequency, 30, ... Verbose, true, ... Plots, training-progress);逻辑说明MiniBatchSize设为 16 是在显存和梯度稳定性之间的折中显存够可以加到 32。InitialLearnRate用 1e-4 而不是 1e-3是因为微调预训练模型时学习率太大会破坏已有特征。LearnRateDropPeriod设为 5表示每 5 个 epoch 学习率乘以 0.1。ValidationFrequency设为 30 表示每 30 次迭代验证一次太小会拖慢训练太大则看不出过拟合趋势。参数上最容易踩的坑是MaxEpochs设得太大。迁移学习通常 10 到 20 个 epoch 就够了再多验证集准确率不升反降那就是过拟合的信号。3.4 用混淆矩阵验证分类效果训练完成后不能只看准确率数字要用混淆矩阵看每个类别的误判情况% 对验证集做预测 predictedLabels classify(net, imdsVal); trueLabels imdsVal.Labels; % 画混淆矩阵 figure; confusionchart(trueLabels, predictedLabels); title(ResNet50 物体分类混淆矩阵);逻辑说明classify返回的是每个样本的预测类别。混淆矩阵的对角线是正确分类非对角线是误判。如果某个类别的误判特别集中说明该类和其他类在特征空间里太接近可能需要增加该类样本或调整数据增强策略。4. VggNet 与 ResNet 对比实验的避坑与排查4.1 显存不足导致训练中断现象训练刚开始就报Out of memory或者 batch size 降到 4 才能跑。原因VggNet 全连接层参数量太大ResNet50 的残差块虽然参数少一些但特征图通道数多激活值占显存。Matlab 默认会预分配显存如果 GPU 显存小于 6GB跑 Vgg16 微调基本没戏。解决优先用 ResNet18 替代 ResNet50或者把 VggNet 当特征提取器而不是端到端微调。具体做法是把trainNetwork换成activations提取fc7层特征后送进fitcecoc训练 SVM。另外把MiniBatchSize降到 8 或 4同时开启ExecutionEnvironment, gpu明确指定 GPU。4.2 输入尺寸不匹配报维度错误现象前向传播时报Expected input to be 224×224×3之类的错误。原因imageDatastore读进来的图片尺寸五花八门而预训练网络要求固定输入尺寸。Matlab 不会自动帮你 resize必须显式指定。解决在imageDatastore里加ReadFcn参数或者在训练前用augmentedImageDatastore统一尺寸augimdsTrain augmentedImageDatastore([224 224 3], imdsTrain); augimdsVal augmentedImageDatastore([224 224 3], imdsVal);然后把trainingOptions里的ValidationData换成augimdsValtrainNetwork的第一个参数换成augimdsTrain。这一步不做后面全是白费。4.3 类别不平衡导致某些类完全被忽略现象混淆矩阵里某个类别的样本几乎全被预测成另一个类。原因如果训练集里 A 类有 500 张、B 类只有 50 张网络会倾向于把样本判给 A 类来降低整体损失。Matlab 默认的交叉熵损失不考虑类别权重。解决在classificationLayer里设置ClassWeights参数给样本少的类别更高权重。或者用oversample对少数类做过采样。我一般会先看countEachLabel的输出如果最大类和最小类样本数差距超过 5 倍就必须处理。4.4 学习率设太大导致 loss 震荡不下降现象训练曲线里 loss 上下剧烈跳动验证准确率始终在随机水平附近。原因微调预训练模型时预训练层的权重已经很好学习率太大会把学到的特征直接冲掉。特别是 VggNet 的全连接层参数量大对学习率更敏感。解决把InitialLearnRate从 1e-3 降到 1e-4 甚至 1e-5同时开启LearnRateSchedule, piecewise。如果还是震荡检查Shuffle是否设为every-epoch数据不打乱也会导致 loss 不稳定。4.5 验证集准确率高于训练集准确率现象训练曲线里验证准确率比训练准确率高出一截看起来「反常」。原因这通常不是 bug而是因为训练时用了 Dropout 或数据增强而验证时没有。Matlab 的预训练网络在全连接层前有 Dropout 层训练时随机丢弃神经元验证时全部启用所以验证表现反而更好。解决不用处理这是正常现象。但如果验证准确率远高于训练准确率且训练准确率一直很低那要检查数据增强是不是太激进或者训练集标签有没有标错。5. 把 VggNet 和 ResNet 用出差异化的三个进阶技巧5.1 用特征融合代替单网络分类VggNet 和 ResNet 学到的特征其实有互补性。VggNet 的浅层卷积核更关注纹理和颜色ResNet 的残差块更关注语义和形状。我试过一个做法分别提取 Vgg16 的fc7层输出和 ResNet18 的pool5层输出拼接成一个长向量再训练一个简单的全连接分类器。在物体类别差异较大的数据集上这种融合特征比单网络能高出 3 到 5 个百分点。具体操作上用activations(net, imds, layerName)分别拿到两个特征矩阵horzcat拼接后送进fitcecoc或fitcsvm。注意两个特征向量的量纲可能不同拼接前最好做归一化。5.2 冻结层数的选择比网络选型更重要很多人纠结选 VggNet 还是 ResNet但实际上冻结多少层对结果的影响更大。我的经验是如果目标数据集和 ImageNet 差异大比如医学影像、工业零件只冻结前 10 到 15 层后面的卷积块全部解冻参与训练。如果差异小比如自然场景下的常见物体冻结到最后一个卷积块之前就够了。在 Matlab 里可以通过设置层的WeightLearnRateFactor为 0 来冻结% 冻结前 10 层 layers net.Layers; for i 1:10 if isprop(layers(i), WeightLearnRateFactor) layers(i).WeightLearnRateFactor 0; layers(i).BiasLearnRateFactor 0; end end逻辑说明WeightLearnRateFactor设为 0 意味着该层权重不更新。isprop判断是为了跳过没有这个属性的层比如输入层、池化层。参数上要注意冻结层数越多训练越快但拟合能力越弱需要根据验证集表现来调。5.3 用 Grad-CAM 看网络到底在关注哪里Matlab 从 R2021a 开始支持gradCAM函数可以可视化网络对某张图片的关注区域。这个技巧在排查「为什么这张图分错了」时特别有用% 对某张验证图片做 Grad-CAM img readimage(imdsVal, 1); scoreMap gradCAM(net, img, predictedLabels(1)); figure; imshow(img); hold on; imagesc(scoreMap, AlphaData, 0.5); colormap jet; title([预测类别: char(predictedLabels(1))]);逻辑说明gradCAM的第三个参数是目标类别返回的scoreMap是热力图颜色越红表示网络越关注该区域。如果热力图集中在背景而不是物体本身说明网络学到了错误的关联这时候需要检查数据集里是不是有背景偏差。注意gradCAM对SeriesNetwork和DAGNetwork都支持但对自定义层可能不兼容。如果报错先确认网络类型。5.4 一个我踩过的坑别在验证集上反复调参最后说一个习惯问题。我早期做物体分类时习惯在验证集上反复试不同的学习率、batch size、冻结层数然后挑验证准确率最高的那组。结果到了测试集上效果差很多。后来才明白验证集被我用成了「第二训练集」模型间接过拟合了验证集。现在的做法是训练集切三份——训练、验证、测试。验证集只用来早停和选模型测试集在最终确定方案之前绝对不碰。如果数据量实在不够至少用交叉验证代替固定验证集。这个习惯比任何网络结构都值钱。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑