基于MATLAB和AlexNet迁移学习的猫狗分类实战

发布时间:2026/10/14 4:33:19
基于MATLAB和AlexNet迁移学习的猫狗分类实战 做猫狗分类这个入门项目很多人第一反应是搭一个CNN从头开始训练。但作为一个用MATLAB做深度学习的老手我更推荐另一条路直接用预训练好的AlexNet做迁移学习。这条路的好处非常直接——不用自己设计网络结构不用从零学海量参数训练时间短准确率还高。这篇文章我就完整记录一下基于MATLAB和Kaggle猫狗数据集的迁移学习全过程从数据准备到网络微调再到测试评估每一步都给出能直接跑的代码和参数顺便聊聊我实操中踩过的那些坑。这个内容适合谁正在学深度学习但不想啃PyTorch或TensorFlow的MATLAB用户做毕设或课程设计需要快速出成果的学生以及想用迁移学习思路解决小数据集分类问题的工程师。读完这篇文章你能在半小时内跑通一个准确率95%以上的猫狗分类器并且理解每一个关键设置到底在干什么。1. 项目思路拆解为什么选MATLAB、AlexNet和迁移学习1.1 迁移学习到底解决了什么问题深度学习圈子里有个默认共识训练一个真正好用的深度模型需要海量数据和大量算力。就拿猫狗分类来说如果从头训练一个类似AlexNet的网络你需要的不只是几千张图片而是几十万甚至上百万张标注好的数据再加上一块高性能GPU训练时间可能是几周甚至几个月。这对绝大多数学习者和普通项目来说根本不现实。迁移学习的思路很朴素把一个在大数据集上学好的模型拿过来只做少量修改和微调然后用小数据跑出好效果。AlexNet是在ImageNet数据集上训练的ImageNet包含上千万张图片、上千个类别模型已经学会了识别边缘、纹理、形状、物体部件这些通用特征。猫和狗虽然是ImageNet里的一千个类别中的两个但模型对这两类物体的底层特征已经有了很强的表征能力。我们要做的只是把最后负责分类的全连接层换掉让模型学会区分“猫”和“狗”这两类而其他卷积层那些提取特征的权重基本不用动顶多做轻微调整。这里有个生活化的类比想象你找了一位精通几百种菜系的厨师你不需要教他认识食材、掌握刀工、控制火候这些基本功只需要告诉他这几天专门做猫粮和狗粮的搭配。迁移学习就是这个逻辑——复用别人花大成本练好的基本功只学你关心的那一小部分。1.2 为什么MATLAB是个好选择我知道很多搞深度学习的人看不起MATLAB觉得不够“工业级”。但在实际项目里MATLAB的深度学习工具箱真有不少实实在在的优势。第一代码量少。用MATLAB做迁移学习核心代码可能不到三十行。你不需要手动处理数据加载、批归一化、学习率调度这些琐碎细节工具箱全部帮你封装好了。第二调试体验好。analyzeNetwork能可视化网络结构deepNetworkDesigner能交互式改网络训练过程中还能实时看准确率曲线对快速验证想法特别友好。第三文档完善。官方文档里针对图像分类的迁移学习教程写得非常详细基本照抄再改改就能用。当然MATLAB不是没有缺点。如果你是搞工业级部署或者需要自定义复杂的网络层那确实应该用PyTorch或TensorFlow。但就“快速跑通一个项目、验证一个想法、做出一个演示系统”这个场景MATLAB的效率真的高得惊人。这也是我在这篇文章里坚持用MATLAB的原因。1.3 AlexNet这个老将为什么依然能打AlexNet这个网络2012年就出来了在当年是大杀器现在看结构其实是比较简单的5层卷积加3层全连接总共约6000万个参数。跟ResNet、EfficientNet这些后来的模型比它精度不是最高的速度也不是最快的。但用它做迁移学习有一个被很多人忽略的优势——结构简单所以更容易上手和理解。对于初学者和快速项目AlexNet的输入尺寸是227×227×3网络深度适中在CPU上也能勉强训练在GPU上更是毫无压力。而且MATLAB里alexnet函数直接就能调起来不需要额外配置模型文件。如果你用ResNet50或GoogLeNet虽然精度可能更高但需要自己处理和下载模型权重网络结构也更复杂对硬件要求更高。所以说AlexNet在“够用”和“简单”之间找到了最好的平衡点。2. 环境准备与数据处理2.1 需要哪些工具和硬件开始之前先确认你的环境。我用了MATLAB R2022b版本深度学习相关功能需要以下工具箱Deep Learning Toolbox核心工具箱必须有Parallel Computing Toolbox可选但要发挥GPU加速就建议装上Computer Vision Toolbox可选有些图像预处理函数工具会用到硬件方面有几点参考意见。CPU方面i5以上就能跑就是慢一点而已一个epoch可能要跑几分钟。GPU方面NVIDIA显卡如果支持CUDA训练速度会有质的提升一块普通入门级独显就能让训练速度快上五到十倍。内存建议至少16GB因为AlexNet本身就有200多MB的权重加上训练过程中的中间变量内存不够容易崩。MATLAB版本不要太老R2021a之前的版本里alexnet需要额外下载模型支持包网络结构版本也比较旧。现在新版本直接一条命令就能载入模型省不少事。2.2 Kaggle猫狗数据集理解与下载Kaggle有一个非常经典的猫狗分类数据集叫Dogs vs. Cats最早是某平台做竞赛用的现在成了图像分类入门的标准数据集。完整数据包含25000张图片猫和狗各12500张图片规格不统一有各种尺寸各种背景非常贴近真实场景。下载方式直接进Kaggle官网找到数据集页面下载就行。不过注意一下Kaggle的那个原始数据集里训练集和测试集是混在一起的没有按猫狗分文件夹。实际做迁移学习的时候我们自己重新划分就好。简单说一下处理逻辑不管你是从网上找的整理好的版本还是自己从原数据里拆最终数据目录应该长这样cats_and_dogs_small/ ├── train/ │ ├── cat/ │ │ ├── cat.0.jpg │ │ ├── cat.1.jpg │ │ └── ... │ └── dog/ │ ├── dog.0.jpg │ ├── dog.1.jpg │ └── ... ├── validation/ │ ├── cat/ │ └── dog/ └── test/ ├── cat/ └── dog/很多人会忽略一个问题如果直接从Kaggle下载文件名是cat.0.jpg和dog.0.jpg这种格式确实可以用文件名区分类别但会让后面的代码复杂不少。直接把图片按类别分到不同的文件夹里MATLAB的imageDatastore就能自动根据子文件夹名生成标签省掉很多麻烦。我个人的划分建议是训练集占70%、验证集占15%、测试集占15%。20000张左右用于训练对AlexNet迁移学习来说完全足够3750张左右用于验证能比较稳定地反映模型的泛化情况剩余约3750张用于最终测试。2.3 用imageDatastore完成数据加载与划分在MATLAB里加载图像分类数据最方便的工具就是imageDatastore。它能自动读取文件夹下的所有图片自动生成标签省的自己写循环读文件。核心代码很简单% 设置数据根目录 dataRoot cats_and_dogs_small; % 创建imageDatastore自动按照子文件夹名标记类别 imds imageDatastore(dataRoot, ... IncludeSubfolders, true, ... LabelSource, foldernames); % 查看数据集信息 disp(imds.Count); % 总图片数 disp(countEachLabel(imds)); % 各类别图片数统计这里有个小细节值得说明LabelSource设为foldernames后MATLAB会按照字母顺序排列类别标签猫cat排在狗dog前面。如果你后面要把标签映射成数字一定要知道cat对应1、dog对应2这个顺序别搞反了。数据划分用splitEachLabel函数按比例切出训练集、验证集和测试集% 先把70%作为训练集剩余30%再对半切分验证集和测试集 [imdsTrain, imdsRemain] splitEachLabel(imds, 0.70, randomized); [imdsVal, imdsTest] splitEachLabel(imdsRemain, 0.50, randomized); % 检查划分结果 disp(countEachLabel(imdsTrain)); disp(countEachLabel(imdsVal)); disp(countEachLabel(imdsTest));randomized参数表示随机抽取图片避免某些图片太相似导致训练集和测试集分布不一致。这一步相当关键如果不随机划分可能把拍摄条件相近的照片全放在训练集里测试的时候就露馅了。2.4 数据增强用小数据集撑起大效果数据增强是迁移学习中容易被新手忽略但效果显著的环节。它的思路很简单不改变图片的语义内容但通过随机变换让模型看到更丰富的样本。比如猫的照片水平翻转一下还是猫但亮度、位置都变了相当于给模型看了一张“新的”猫照片。MATLAB里做数据增强用的是augmentedImageDatastore。对AlexNet来说它的输入尺寸是227×227×3所以系统会自动把图片缩放或裁剪到这个尺寸。在此基础上可以叠加随机平移、翻转、缩放、旋转等变换% 定义输入尺寸 inputSize [227 227 3]; % 创建增强数据存储同时完成尺寸统一 augTrain augmentedImageDatastore(inputSize, imdsTrain, ... DataAugmentation, imageDataAugmenter(... RandXTranslation, [-10 10], ... % 水平随机平移 RandYTranslation, [-10 10], ... % 垂直随机平移 RandXScale, [0.9 1.1], ... % 随机缩放 RandXReflection, true)); % 随机水平翻转 % 验证集也做尺寸调整但一般不做数据增强避免评估不稳定 augVal augmentedImageDatastore(inputSize, imdsVal);这里要解释一个细节为什么验证集不做随机变换因为验证集用来评估模型真实水平如果每次都做随机翻转和缩放你看到的准确率曲线会非常不稳定没法判断模型是不是真的在变好。验证集只需要统一尺寸让网络能接受就行。3. AlexNet迁移学习的核心实现3.1 加载预训练模型并修改网络结构MATLAB里加载AlexNet特别省事一条命令就搞定net alexnet;这条命令做了三件事确认Deep Learning Toolbox已安装、自动下载AlexNet的预训练权重约227MB第一次运行需要联网、把网络返回给net变量。如果你的网络状况不太好MATLAB支持手动下载模型权重放到本地再加载避免反复中断。加载完成后用analyzeNetwork(net)可以可视化网络结构你会看到网络从输入层到输出层一共25层。关键在最后三层第23层全连接层fc8输出1000个神经元 第24层Softmax层 第25层分类输出层原来的1000个输出对应ImageNet的1000个类别我们要改成2个猫和狗。修改方法不是直接改原网络而是先拆解成层图替换掉最后三层% 将网络转换为层图方便修改 lgraph layerGraph(net); % 找到要替换的层 fcLayer lgraph.Layers(end-2); % 原来的全连接层 % 实际上更稳妥的做法是按名字找不同版本名字可能不同 % 显示一下层名确认 analyzeNetwork(lgraph); % 替换为新的全连接层、softmax层和分类层 newLayers [ fullyConnectedLayer(2, Name, fc_new, ... WeightLearnRateFactor, 10, BiasLearnRateFactor, 10) softmaxLayer(Name, softmax_new) classificationLayer(Name, classoutput_new) ]; % 用新层替换旧的最后三层 lgraph replaceLayer(lgraph, fc8, newLayers(1)); lgraph replaceLayer(lgraph, prob, newLayers(2)); lgraph replaceLayer(lgraph, output, newLayers(3)); % 检查修改后的网络 analyzeNetwork(lgraph);这里有个新手常犯的错误他们可能只把全连接层改成了2个输出但忘了softmax层和分类输出层的名字也要跟着改。如果你调用replaceLayer时指定的名字不对MATLAB会直接报错所以用analyzeNetwork先看清楚层名是稳妥的步骤。关于为什么新加的fullyConnectedLayer要设置WeightLearnRateFactor为10这背后的逻辑值得说道说道。原网络卷积层的权重已经训练得很好了我们基本不想动它所以学习率保持默认等于1倍全局学习率就行。但新的全连接层是从随机权重开始的需要更大的学习率才能快速收敛。把它设成全局学习率的10倍意味着在同样的训练轮数里新层的学习速度会比旧层快一个数量级这样就能用较短时间把新层训练到位。3.2 训练选项的配置与参数详解训练选项函数是trainingOptions这套参数直接影响最终效果和训练时间。我用过的比较合适的一套配置options trainingOptions(sgdm, ... MiniBatchSize, 32, ... MaxEpochs, 10, ... InitialLearnRate, 1e-4, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.5, ... LearnRateDropPeriod, 4, ... Shuffle, every-epoch, ... ValidationData, augVal, ... ValidationFrequency, 50, ... Plots, training-progress, ... Verbose, true, ... ExecutionEnvironment, auto);逐项解释一下这些参数的含义和取值逻辑MiniBatchSize设成32的意思是每次迭代只把32张图片喂给网络。这个值不能太大不然显卡内存会吃不消也不能太小太小训练不稳定且浪费时间。32是一个比较均衡的选择如果你的显卡显存低于4GB改成16也问题不大。AlexNet在批大小为32时单次迭代在普通GPU上大概耗时0.1到0.5秒整体训练时间可控。MaxEpochs设为10代表完整跑10遍训练集。这个数字看起来小但因为用了预训练权重通常5到8个epoch准确率就已经很高了10个epoch足够收敛。如果设得太大容易过拟合训练集准确率接近100%但验证集反而掉下来。InitialLearnRate设为1e-4这是迁移学习最重要的一个参数。从头训练CNN通常用0.01到0.1的学习率但迁移学习绝对不能这么干。原因很简单原网络的权重已经很好了学习率太大一步更新就可能把精心训练好的权重彻底打乱这叫“灾难性遗忘”。1e-4是一个保险的起点既能让新层快速学习又不会破坏底层的特征提取能力。LearnRateSchedule设成piecewise表示分段衰减学习率每训练LearnRateDropPeriod个epoch学习率就乘上LearnRateDropFactor0.5也就是说训练到第4个epoch时学习率变成5e-5到第8个epoch时变成2.5e-5模型越来越接近最优解时步子应该越迈越小避免在最优解附近来回震荡。Shuffle设为every-epoch意思是每个epoch开始前都重新打乱训练数据的顺序。这能防止模型学到数据排序中的固定模式对收敛稳定性有明显帮助。ValidationFrequency设为50意思每迭代50次就在验证集上测一次准确率。如果设得太频繁训练过程会变慢设得太稀少你很难实时判断模型表现。ExecutionEnvironment设为autoMATLAB会自动检测是否有可用GPU有就自动用GPU没有就回退到CPU。3.3 训练模型与保存结果配置好一切之后调用trainNetwork函数就能开始训练% 开始训练 [netTransfer, info] trainNetwork(augTrain, lgraph, options); % 保存训练好的模型 save(alexnet_cats_dogs.mat, netTransfer);训练过程中MATLAB会弹出一个实时训练进度窗口你会看到损失曲线和准确率曲线一起变化。正常情况下第一个epoch结束时准确率应该能达到85%以上第二三个epoch到90%以上最终稳定在95%以上。如果训练完成后准确率还没上90%通常说明学习率设太大或者数据划分有问题需要回头检查。info结构体里保存了训练过程的详细记录包括每个epoch的损失值、验证准确率、迭代次数等。如果你画训练曲线这些都是很有用的原始数据。如果硬件有限跑起来特别慢有几个办法把MiniBatchSize调到16甚至8减少内存压力把MaxEpochs降到5先看效果不够再接着训练直接用训练好的模型跳过重新训练这一步骤。3.4 在测试集上评估模型性能训练只是完成了“让模型学会分辨”真正的考验是在测试集上。用classify函数对每张测试图片做预测然后跟真实标签比对% 读取测试集原图不做数据增强 testTbl countEachLabel(imdsTest); disp(testTbl); % 对测试集图片做尺寸统一 augTest augmentedImageDatastore(inputSize, imdsTest); % 分类预测 predLabels classify(netTransfer, augTest); % 获取真实标签 trueLabels imdsTest.Labels; % 计算准确率 accuracy sum(predLabels trueLabels) / numel(trueLabels); fprintf(测试集准确率: %.2f%%\n, accuracy * 100); % 生成混淆矩阵 confusionchart(trueLabels, predLabels);混淆矩阵是个好工具它不仅能告诉你整体准确率还能看出具体哪里错了。比如你可能看到猫的准确率是97%狗的准确率是94%说明模型对狗的区分能力稍弱。这时候可以针对性做数据增强比如把狗的图片多做一些随机旋转、裁剪增加样本多样性后再试试。对于单张图片的预测可以这样玩img imread(test_mycat.jpg); img imresize(img, inputSize(1:2)); label classify(netTransfer, img); disp(label);这里注意一点imresize直接缩放会破坏图片的长宽比。AlexNet要求输入是227×227的正方形如果你的图是长方形直接缩放会产生畸变。更好的办法是用augmentedImageDatastore内部的处理逻辑它会先对图片做缩放再居中裁剪到目标尺寸这样保留的画面信息和实际训练时的预处理方式一致预测效果更好。4. 常见问题与排查经验实录4.1 训练准确率上不去卡在50%左右这是最经典的错误准确率50%就意味着分类器完全在瞎猜比随机好不了多少。我在做这个项目的过程中遇到过几次排查思路基本是这样。检查标签是否是乱序的。如果imageDatastore读取时子文件夹排序不可控可能出现“类别1是狗”而“类别2是猫”的情况。用countEachLabel(imdsTrain)看输出确认猫对应第一个类别、狗对应第二个类别。对初学者来说这一步可能是最容易疏忽的环节。检查全连接层修改是否正确。把新网络的fc8层的OutputSize打印出来确认是不是2。有时候你做了多次修改层名和结构都已经变了输出层仍然保留了1000个类别那肯定训不好。检查学习率是否设置过大。如果我用了0.01甚至0.1这样的大学习率训练损失会一直震荡准确率曲线像锯齿一样来回摆动。迁移学习的学习率应当保持在1e-4或更小的水平这个原则真的是经验总结出来的不用走弯路。4.2 验证准确率很高但测试准确率低这是典型的过拟合信号。模型在验证集上表现完美但一遇到没见过的照片就露馅了因为它在训练过程中记住了特定训练样本的影像模式而不是学会识别“猫”这个物种的通用特征。解决过拟合的办法主要靠数据增强。把RandXTranslation和RandYTranslation的幅度调大一些比如从10像素增加到30像素增加RandScale的幅度到[0.8 1.2]让图片尺寸变化更明显。也可以额外引入随机亮度调整让模型适应不同的光照条件。第二个办法是给新加的全连接层加正则化。把fullyConnectedLayer里的WeightL2Factor从默认值调大比如设成0.01让权重不要长得太大通常能改善泛化。第三个办法更直接——用更多训练数据。如果条件允许把训练集扩大用更多猫狗图片。数据量上来了过拟合就会明显缓解。4.3 训练时间太长怎么办如果你没有独立显卡只用CPU跑整个模型10个epoch可能要等上一到两个小时体验确实折磨。最快的替代方案是减少训练规模。把MaxEpochs降到5通常也能得到90%以上的准确率。或者用早停策略只看验证准确率曲线一旦连续几个epoch没有明显提升就可以手动中断训练直接保存当前最好的模型。另一个思路是换用更小的网络。比如用MATLAB里的googlenet或squeezenet代替AlexNet网络规模小好几倍训练速度会快很多准确率并不会差太多。不过这篇文章主要讲AlexNet这个优化思路读者可以自行尝试。4.4 代码运行时报错找不到alexnet确认是否安装了Deep Learning Toolbox。在MATLAB命令行输入ver在弹出的窗口里查看是否列出了Deep Learning Toolbox如果没有说明需要安装。确认模型支持包是否下载。旧版MATLAB中alexnet模型不是内置的需要单独下载支持包。在MATLAB的“附加功能”里搜索“AlexNet”可以找到模型支持包。新版R2021a之后一般不需要但如果没联网同样无法下载模型权重启动时会报低层错误用不了网络。MATLAB版本过旧也容易出问题。有些很老的版本里alexnet函数根本不存在只能通过importCaffeNetwork载入外部模型操作复杂很多。建议直接升级到R2021a以上的版本省心省力。4.5 做一个能跑的图片分类实时小工具训练完模型之后如果你还想更进一步可以顺手写一个简单的交互小工具调用电脑摄像头或者你选一张本地图片一键识别猫狗。这会让你更有成就感。用MATLAB的uigetfile函数选择图片axes显示图片再调用训练好的模型进行分类几十行代码就能搭出一个像模像样的小系统。这已经是这个项目比较进阶的玩法了用到真实的用户界面编程适合做毕设展示或者朋友面前的演示。5. 更进一步的优化方向这个项目跑通之后如果想要更深入还有几个扩展角度值得结合自己的目标去挖掘。首先是做模型对比实验。把AlexNet换成GoogLeNet、ResNet50、SqueezeNet在同一个数据集上做迁移学习对比各模型的准确率、训练时间和模型大小。这种对比分析会大大提升项目的含金量。我当时做这个实验的结果是ResNet50准确率比AlexNet高约1.5%但模型体积大将近四倍训练时间也长一些SqueezeNet虽然准确率稍低一点但模型体积只有几MB训练超快。具体怎么选还是要看你的应用场景。其次是尝试数据增强的不同策略。比如加入随机亮度调整、随机色彩抖动、随机旋转角度等看看对模型的鲁棒性有多大提升。这里可以做一个消融实验每组实验只改变一个变量对比准确率指标既好做又有说服力。如果想把这个项目做成一个更完整的演示系统可以GUI界面加上实时摄像头识别功能。把训练好的模型打包成一个可执行程序这在某些场景下非常实用MATLAB的Compiler组件可以把模型部署成独立的应用程序让别人在没有MATLAB环境的情况下也能跑起来。最后如果你对模型内部运作原理感兴趣可以用deepDreamImage函数让模型自己生成“它想象中猫的样子”虽然结果往往怪异的很但这个过程能让你直观感受卷积神经网络到底学到了什么特征。这在写项目报告或者做展示的时候会是非常出彩的素材。我个人在实际操作中有一个体会最深刻迁移学习这个事儿学习率真的决定一切。第一次跑的时候我用了0.001结果训练到大概第3个epoch损失曲线就跟心跳一样上下震荡验证准确率死活不涨后来老老实实把学习率调回1e-4第二个epoch就已经能到88%。这个教训让我后来每次做迁移学习都会有意识地先把学习率焊死在小数点后第四位效果一直很稳定。最后再分享一个小技巧如果你训练过程中发现验证准确率到了93%左右就再也上不去别急着调网络结构先看看是不是验证集里有些图片本身就很难判断——比如一只戴着猫项圈的狗或是一只长得很像狗的猫。给混淆矩阵多看几眼你能发现自己数据的“天花板”到底在哪这样心里就有数了不会在参数上瞎折腾。总之把基础版本跑通之后按照自己的需要对网络结构和数据策略做出调整这个项目给你的收获会远远超过“能分类猫狗”这一点。

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询