简介:这份资源围绕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 训练,基本等于自虐;即便用 GPU,batch 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换成augimdsVal,trainNetwork的第一个参数换成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、冻结层数,然后挑验证准确率最高的那组。结果到了测试集上效果差很多。后来才明白,验证集被我用成了「第二训练集」,模型间接过拟合了验证集。
现在的做法是:训练集切三份——训练、验证、测试。验证集只用来早停和选模型,测试集在最终确定方案之前绝对不碰。如果数据量实在不够,至少用交叉验证代替固定验证集。这个习惯比任何网络结构都值钱。
希望帮到你。
本文还有配套的精品资源,点击获取