
简介本资源是一份面向深度学习初学者与MATLAB用户的卷积神经网络CNN实践教程聚焦图像分类等典型任务解决从理论理解到代码实现的落地难题。压缩包共31个文件以30个核心MATLAB脚本.m为主涵盖前向传播cnnff.m、反向传播cnnbp.m、参数更新cnnapplygrads.m、训练主流程cnntrain.m、测试评估cnntest.m及数据预处理im2patches.m、whiten.m、normalize.m等辅以1个MNIST图像数据集mnist_uint8.mat完整复现了CNN在MATLAB中的底层构建与端到端训练流程。已有2933人学习下载资源结构清晰、模块解耦明确不仅提供可直接运行的示例test_example_CNN.m还包含梯度检验cnnnumgradcheck.m、滤波器可视化visualize.m、LM滤波器生成makeLMfilters.m等辅助分析脚本便于深入理解卷积机制、调试网络行为并开展二次开发。 前阵子不少人在社区里问我MATLAB到底能不能搞CNN卷积神经网络是不是必须得转Python。这个问题我特别有发言权——我在MATLAB里从零搭过图像分类网络也踩过显存不够、训练不收敛、维度对不上这些坑。这篇笔记就把我这几年的实际操作经验捋一遍从数据准备到网络搭建、训练配置、模型评估再到1D CNN和注意力机制的扩展方向尽量写成一份能直接跟着做、能省时间的东西。1. 为什么我会在MATLAB里做卷积神经网络1.1 MATLAB在深度学习里的真实定位很多人一聊深度学习默认就是TensorFlow、PyTorch加PythonMATLAB似乎只是用来做矩阵计算和仿真的老古董。但我个人用过之后的结论是MATLAB的Deep Learning Toolbox早就不是附属品了它已经把“数据准备—网络搭建—训练—评估—部署”这整条链路都做成了图形化和函数化非常适合已经有MATLAB环境的人。尤其是你已经在MATLAB里做图像处理、信号处理甚至Simulink仿真再从零去搭一套Python环境其实很折腾。而CNN本身的核心就是卷积、池化、全连接这些矩阵运算MATLAB做这些计算属于老本行。我甚至觉得对于课程作业、毕业设计、科研验证这类场景MATLAB反而比Python上手更快因为不需要处理环境配置、依赖版本这些琐事。1.2 工具箱、版本和硬件的基本要求想在MATLAB里跑CNN光有基础版MATLAB不够必须确认你的许可证包含Deep Learning Toolbox。我对版本的建议是只要不是太老的版本R2019b之后基本都能正常工作最新的R2022b、R2023a、R2025b这些版本里工具箱提供的层类型和选项更全用起来也更顺手。硬件方面训练CNN最理想的平台是有NVIDIA显卡的机器支持CUDA。如果没有独立显卡纯CPU也能训练只是速度会慢很多。我在一台只有CPU的笔记本上跑过一个几十层的小网络尽管epoch不多一个epoch也要等好几分钟连跑十几个epoch相当考验耐心。1.3 什么场景下用MATLAB做CNN最划算从我接触到的实际项目和提问看下面这几类人最适合在MATLAB里做CNN做图像分类、目标识别课程作业的学生需要快速跑通整个流程。已经用MATLAB做信号分析、故障诊断、电池状态估计的工程师想把CNN作为特征提取器嵌入现有流程。做论文复现的研究人员需要在已有工具箱基础上快速验证网络效果。如果你的任务涉及超大规模数据集、需要部署到手机或Web端那建议还是用Python生态但在“快速验证想法”这件事上MATLAB这套工作流的开发效率真的很香。2. 数据准备imageDatastore决定了你下一步顺不顺利2.1 用文件夹结构组织数据是最省事的方式我见过很多新手在数据加载这一步就卡住了其实MATLAB里有个特别方便的数据接口叫imageDatastore它最大的优势是直接从文件夹目录结构读取图片并把文件夹名作为样本标签。假设你有一个“roadsigns”数据集目录结构如下roadsigns/ ├── stop/ │ ├── img001.jpg │ ├── img002.jpg │ └── ... ├── turnleft/ │ ├── img001.jpg │ └── ... └── turnright/ └── ...加载数据就两行代码imds imageDatastore(roadsigns, ... IncludeSubfolders, true, ... LabelSource, foldernames);这里IncludeSubfolders一定要设为true否则子文件夹里的图片不会被扫描到。LabelSource设为foldernames后MATLAB会自动把每个子文件夹名转换成categorical类型的标签省去手动标注的麻烦。加载完之后可以用countEachLabel快速看每个类别的图片数量分布countEachLabel(imds)这条统计非常重要如果你发现某个类别的图片特别少就需要提前做数据增强或者考虑类别均衡问题。2.2 训练集、验证集、测试集的划分细节拿到数据集后不能一股脑全拿去做训练。我惯用的划分比例是70%训练、15%验证、15%测试。用splitEachLabel就能按比例随机划分[imdsTrain, imdsVal, imdsTest] splitEachLabel(imds, 0.7, 0.15, 0.15, randomized);注意最后这个randomized参数很重要加上它才能把样本顺序打乱避免出现某个类别全部排在一起导致划分不均匀。你还可以传rng(0)来固定随机种子这样每次运行得到的数据划分结果一致方便复现实验。关于验证集和测试集的作用一定要分清验证集用于训练过程中监测模型是否过拟合测试集用于最终评估模型效果。我最开始总想省事只分训练集和测试集结果训练过程中完全看不到泛化趋势等训完才发现模型早就过拟合了。所以验证集千万别省。2.3 数据增强小数据集救星的正确配置CNN对数据量特别敏感数据量少就很容易过拟合。MATLAB里头做数据增强很方便用imageAugmenter配置增强策略再用augmentedImageDatastore包一层即可。举一个我常用的配置augmenter imageAugmenter( ... RandRotation, [-5 5], ... RandXTranslation, [-3 3], ... RandYTranslation, [-3 3], ... RandXScale, [0.9 1.1], ... RandYScale, [0.9 1.1]);这里代表每次读取图像时以5度以内的随机旋转、3像素范围内的随机平移、10%以内的随机缩放来生成一个新的增强版本相当于让模型每次看到的都是“不完全一样”的训练样本泛化能力自然更强。我最想提醒的是两个关键点验证集和测试集不要做随机增强只做尺寸统一。因为验证集和测试集要反映模型的真实泛化能力如果也加了随机扰动评估结果不稳定甚至偏乐观。增强幅度不要太大。以前我做字符识别时把旋转角度设到正负30度结果训练集上表现很漂亮测试集上成绩反而不稳定因为一些数字被旋转后已经接近另一个数字了反而引入噪声。2.4 数据准备阶段的三个常见坑第一个坑中文路径。MATLAB在不同操作系统下的图像读取对中文路径支持不是特别稳定我遇到过读取到一半报路径找不到的情况。建议所有数据集路径都用英文命名省事。第二个坑图片尺寸不一致。如果你的数据集里图片有横屏有竖屏有大有小直接拿去做训练容易触发尺寸不匹配的报错。解决办法很简单在augmentedImageDatastore里指定一个统一输出尺寸它会自动缩放augimdsTrain augmentedImageDatastore([28 28 1], imdsTrain, DataAugmentation, augmenter); augimdsVal augmentedImageDatastore([28 28 1], imdsVal); augimdsTest augmentedImageDatastore([28 28 1], imdsTest);第三个坑忘记检查标签顺序。imageDatastore自动生成的标签顺序是按文件夹名排序的如果测试时你手动用readimage取图再手动定义一个标签数组很容易和splitEachLabel之后的顺序对应不上。建议一律使用数据存储对象默认输出的Labels属性不要自己重新构造。3. 搭建网络每一层都要知道为什么这么放3.1 一个能跑起来的最小CNN长什么样以手写数字识别为例输入是28x28的灰度图我自己最常搭建的最小可跑结构是这样的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) maxPooling2dLayer(2, Stride, 2, Name, pool2) fullyConnectedLayer(10, Name, fc) softmaxLayer(Name, softmax) classificationLayer(Name, output)];这个结构虽然简单但包含了CNN的核心模块卷积层提取局部特征批归一化层稳定分布ReLU激活层引入非线性池化层压缩空间尺寸全连接层做分类Softmax输出类别概率。3.2 卷积核大小、数量与特征图尺寸的换算逻辑很多初学者一上来就问“卷积核选3还是5”“第一层用几个滤波器”我觉得得先搞清楚特征图尺寸怎么算才能真正理解网络设计。输出特征图的尺寸公式是输出尺寸 (输入尺寸 - 滤波器尺寸 2 * Padding) / Stride 1比如输入28x28卷积核3x3Padding设为sameStride默认为1那么输出还是28x28。如果不用Padding输出就是26x26。为什么第一层用8个滤波器因为对于MNIST这类简单任务边缘、端点、弧线这些基础特征数量并不多。如果把第一层滤波器数直接设成64甚至128参数量会暴涨训练也会更慢。通常我遵循一个经验法则第一层从8或16起步之后每层翻倍最后一层不要超过128或256。这能让网络在小数据集上也稳定训练。下面这个表可以直观展示前面那个小网络的特征图尺寸和参数量变化层名输入尺寸输出尺寸参数量估算input-28x28x10conv1 (3x3, 8)28x28x128x28x83x3x1x8880pool1 (2x2, stride2)28x28x814x14x80conv2 (3x3, 16)14x14x814x14x163x3x8x16161168pool2 (2x2, stride2)14x14x167x7x160fc (10)7x7x1678410784x10107850注意全连接层的输入维度是把前面所有通道的空间特征全部展平后的长度。7x7x16等于784所以全连接层第一个维度必须是784。很多报错都出在这里后面我会专门展开讲排查方法。3.3 analyzeNetwork是检查网络结构的神器搭好网络之后先别急着训练我强烈建议先在命令行执行analyzeNetwork(layers)它会弹出网络结构可视化窗口逐层标注每层的尺寸并在有维度不匹配的地方直接给出警告。这个工具救过我很多次尤其是网络层数多了以后靠人肉算特征图尺寸很容易出错。还有一个用途是看总参数量。深度学习不是“层越多越好”你得观察每一层的参数规模和计算量避免设计出一个参数量又大、效果又不好的“四不像”网络。3.4 别急着上预训练模型小网络的性价比我见过一种倾向明明数据集只有几千张图片一上来就要用ResNet101或者EfficientNet。这种做法在MATLAB里虽然实现起来很简单几行代码加载预训练模型但要注意几个问题一是预训练模型输入尺寸通常是224x224x3你需要resize数据这会增加CPU和GPU负担二是如果数据量不够微调阶段极其容易过拟合三是网络层数深了训练时间成倍增长。我的建议是先用一个浅层小网络把整套流程跑通比如上面那个两层卷积的小网络。跑通之后如果需要提升精度再考虑迁移学习。遇到瓶颈时先用预训练的ResNet18做特征提取通常能比随机初始化的模型好很多。4. 训练配置trainingOptions里每个参数都不是摆设4.1 求解器怎么选SGDM最稳、Adam最省心MATLAB的trainingOptions支持多种求解器我常用的主要是sgdm带动量的随机梯度下降和adam。讲真对于大多数CNN任务我更推荐先用SGDM。它的收敛虽然比Adam慢一点但稳定、好调训练曲线看起来更可控。Adam的优势在于自适应学习率初始参数设置对结果不那么敏感适合快速验证。如果时间紧、不想反复调学习率可以先试Adam等确定网络结构没问题了再用SGDM做最终训练。求解器选择没有绝对的对错我自己的习惯是小数据集、浅层网络直接用SGDM大数据集、深网络、不确定学习率该设多少时先用Adam跑通。4.2 学习率与批次大小的调配套路我经常被问到学习率设置多少合适。直接说结论对大多数图像分类任务初始学习率在0.001到0.01之间比较合适。如果用的是预训练模型学习率要更小通常0.0001到0.0003。MiniBatchSize批大小则受显存限制。显存充足时批大小可以到128或256显存紧张时64甚至32也能训练。批大小太小训练过程震荡会比较明显批大小太大训练速度快但有时候泛化效果反而稍差。我现在固定套路是先用128跑一遍看曲线如果震荡明显就降到64如果显存不够就降到32。一个典型训练选项配置长这样options trainingOptions(sgdm, ... InitialLearnRate, 0.01, ... MiniBatchSize, 128, ... MaxEpochs, 20, ... Shuffle, every-epoch, ... ValidationData, augimdsVal, ... ValidationFrequency, 30, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.1, ... LearnRateDropPeriod, 10, ... L2Regularization, 0.0001, ... Verbose, true, ... Plots, training-progress);这里Shuffle设为every-epoch是让每个epoch训练前重新打乱数据顺序避免模型学到样本顺序带来的假规律。ValidationFrequency表示每30次迭代评估一次验证集。LearnRateSchedule配合LearnRateDropPeriod意思是每10个epoch学习率乘以0.1这个衰减策略能让训练后期更平稳地收敛到局部最优。L2Regularization是权重衰减防止过拟合默认0.0001已经够用不需要额外增加。4.3 训练可视化与验证频率的设置我喜欢把Plots设为training-progress这样训练过程中会实时画出训练损失、训练准确率、验证损失和验证准确率非常直观。一般我判断训练是否健康主要看两条曲线训练损失是否持续下降验证准确率是否同步上升。训练初期验证准确率可能有起伏这很正常。但如果训练损失已经降到很低的水平验证损失反而升上去那基本就是过拟合的迹象这时候要考虑增加数据增强、加入Dropout层、减小模型规模或者提前停止训练。MaxEpochs可以设置得大一点比如50然后配合早停策略。实际上trainingOptions里有个ValidationPatience参数意思是验证损失连续多少轮没有改善就自动停止训练。设定为5或10都比较合理这样可以防止训练时间被白白浪费。4.4 显卡不够时怎么把训练跑完不是所有人都有一块大显存显卡。如果你在训练过程中遇到“out of memory”之类的报错我建议按下面的顺序排查检查GPU信息执行gpuDevice查看当前显存占用情况。把MiniBatchSize降到64、32甚至16这是最有效的办法。降低输入图像分辨率。比如原来用224x224输入可以降到112x112很多任务里精度损失完全在可接受范围内。如果模型特别大考虑换用更简洁的网络结构。最后如果以上都不行可以在trainingOptions里把ExecutionEnvironment设为cpu但要做好心理准备训练时间会显著变长。还有一个小技巧在训练之前检查一下是否可以使用GPUif canUseGPU() disp(GPU可用) end这样可以避免训练到一半才发现一直在用CPU。5. 完整实战训练一个手写数字分类器5.1 数据准备与网络定义这里我给一个可以直接照抄的完整流程假设你已经把MNIST风格的图片存到了mnist_data文件夹下内部是0到9共10个子文件夹。首先是数据加载和划分imds imageDatastore(mnist_data, ... IncludeSubfolders, true, ... LabelSource, foldernames); [imdsTrain, imdsVal, imdsTest] splitEachLabel(imds, 0.7, 0.15, 0.15, randomized); countEachLabel(imdsTrain)接下来定义增强器和增强后的数据存储对象augmenter imageAugmenter(RandRotation, [-5 5], RandXTranslation, [-2 2], RandYTranslation, [-2 2]); augimdsTrain augmentedImageDatastore([28 28 1], imdsTrain, DataAugmentation, augmenter); augimdsVal augmentedImageDatastore([28 28 1], imdsVal); augimdsTest augmentedImageDatastore([28 28 1], imdsTest);然后定义网络结构。为了让识别更稳我在第三章那个两层卷积网络的基础上把滤波器数量调大了一点layers [ imageInputLayer([28 28 1], Name, input) convolution2dLayer(3, 16, Padding, same, Name, conv1) batchNormalizationLayer(Name, bn1) reluLayer(Name, relu1) maxPooling2dLayer(2, Stride, 2, Name, pool1) convolution2dLayer(3, 32, Padding, same, Name, conv2) batchNormalizationLayer(Name, bn2) reluLayer(Name, relu2) maxPooling2dLayer(2, Stride, 2, Name, pool2) fullyConnectedLayer(10, Name, fc) softmaxLayer(Name, softmax) classificationLayer(Name, output)]; analyzeNetwork(layers)5.2 训练与监控训练配置方面我建议用SGDM初始学习率0.01批大小128最大epoch设20。由于数据增强已经引入了随机性训练前每个epoch也会自动打乱顺序options trainingOptions(sgdm, ... InitialLearnRate, 0.01, ... MiniBatchSize, 128, ... MaxEpochs, 20, ... Shuffle, every-epoch, ... ValidationData, augimdsVal, ... ValidationFrequency, 50, ... LearnRateSchedule, piecewise, ... LearnRateDropFactor, 0.1, ... LearnRateDropPeriod, 10, ... Plots, training-progress, ... Verbose, false); net trainNetwork(augimdsTrain, layers, options);训练过程中如果看到验证准确率一直上不去不要干等着先中止训练检查是数据问题还是网络问题。等训练完成命令行输出的net对象就是训练好的模型。5.3 测试评估与混淆矩阵训练完成后在测试集上评估YPred classify(net, augimdsTest); YTest imdsTest.Labels; accuracy mean(YPred YTest); fprintf(测试集准确率: %.2f%%\n, accuracy * 100); figure; confusionchart(YTest, YPred);confusionchart会画出混淆矩阵对角线越亮代表分类越准。我最常用它来发现“哪两个类别容易混淆”如果数字3和8经常互相认错那就说明这两类样本的特征区分度不够需要增加这两类样本的数量或增强。如果需要逐类看精确率和召回率可以这样写figure; cm confusionchart(YTest, YPred); cm.Normalization row-normalized;5.4 模型保存、加载与部署训练完后模型保存和加载非常简单save(trained_mnist_cnn.mat, net);下次使用直接加载load(trained_mnist_cnn.mat, net);如果你需要把模型导出成通用格式MATLAB支持导出ONNX格式exportONNXNetwork(net, trained_mnist_cnn.onnx);这个格式可以被PyTorch、TensorFlow读取做跨平台部署很方便。6. 我在训练过程中踩过的坑和排查思路6.1 显存不足报错信息和我的解决路径有一次训练一个三通道彩色图像分类模型输入224x224x3批大小256训练到第60个迭代直接报错信息里有“out of memory on device”。我当时的排查步骤是先执行gpuDevice看显存占用发现其他进程占了不少显存。关闭别的进程后依然报同样的错误说明模型占用的显存确实超过了剩余容量。把MiniBatchSize从256降到128问题依旧。将输入尺寸从224x224降到160x160同时把批大小降到64终于正常训练。从这里能明显看出显存占用的大头是特征图大小和批大小。如果你用的预训练模型输入要求224x224那尽量不要随意改输入尺寸优先降批大小比较稳妥。6.2 维度对不上特征图的数值得自己会算我在第三章已经给过特征尺寸计算公式但在实际使用中还是会遇到维度报错比如“Layer fc: Input size does not match”之类的信息。这时候我的排查习惯是先把analyzeNetwork跑一遍它通常会在可视化窗口中直接标出哪一层维度不匹配。如果MATLAB没有标出来那就手动算。从输入层开始一层一层记录输出尺寸特别关注池化层和卷积层的Stride参数。绝对不要在报错后随手改全连接层的数值先搞清楚上一层的输出维度是多少。举一个实战例子如果输入是32x32x3经过5x5卷积核、Padding同、Stride2之后输出尺寸是(32-52*2)/21 16所以输出是16x16。这个数字必须在设计全连接层时记下来。6.3 训练震荡不收敛从学习率和数据归一化入手有段时间我做一个工业零部件缺陷分类训练损失一直在1.0附近反复横跳验证准确率停留在40%左右。排查时我先怀疑的是学习率从0.01降到0.001后损失开始下降但幅度依然不够理想接着检查数据分布发现图片以uint8形式输入像素值在0到255之间没有做归一化。把输入改成0到1范围后训练效果立刻改善最终准确率从40%提升到92%以上。这个案例里最大的教训是在CNN训练中输入数据的量纲和分布对收敛影响很大。使用augmentedImageDatastore时一般会自动转换但如果你自己写数据读取循环很容易忽略这一步。还有一个可能的原因网络里没有BatchNorm层。对于浅层网络不加BatchNorm可能没事但网络稍微深一点梯度分布不稳定就会导致训练震荡。我的原则是只要网络超过3层卷积就在每个卷积后面加BatchNorm。6.4 虚拟机里越跑越慢的处理经验有人问我在虚拟机上跑MATLAB深度学习怎么特别慢。这个问题我确实遇到过。虚拟机里如果没能把物理GPU直通进去MATLAB的canUseGPU会返回false训练就退化到CPU模式而虚拟机的CPU性能往往还要再打折扣所以特别慢。我的经验是如果你只是做小规模实验可以把网络结构做得尽量小输入尺寸和MiniBatchSize都调低。如果是正式训练还是建议放到物理机上跑。如果实在要在虚拟机上跑可以尝试用MATLAB的并行计算功能多开几个CPU worker对纯CPU训练有一定加速效果但别期待质的飞跃。7. 从图像到信号1D CNN和注意力机制的扩展方向7.1 用1D CNN处理时序信号CNN不是只能处理图像。在故障诊断、生物电信号分析、语音识别这些场景里一维信号也经常用1D CNN来提取局部特征。MATLAB中提供了convolution1dLayer用法和二维卷积非常类似。以一段长度为128的传感器信号为例如果数据以特征矩阵形式组织可以直接用featureInputLayer加convolution1dLayer如果是变长序列则用sequenceInputLayer。我建议的思路是先把数据整理成固定长度的特征矩阵用1D CNN处理。比如每条样本是一个128维的向量网络结构可以这样layers1D [ featureInputLayer(128, Name, input) convolution1dLayer(3, 16, Padding, same, Name, conv1) reluLayer(Name, relu1) maxPooling1dLayer(2, Stride, 2, Name, pool1) convolution1dLayer(3, 32, Padding, same, Name, conv2) reluLayer(Name, relu2) globalAveragePooling1dLayer(Name, gap) fullyConnectedLayer(numClasses, Name, fc) softmaxLayer(Name, softmax) classificationLayer(Name, output)];这里用globalAveragePooling1dLayer代替了全连接层作为特征压缩效果通常比直接把长向量展平更好参数也更少。7.2 注意力机制在MATLAB里的实现思路现在很多论文里都会加注意力机制比如SENet、CBAMMATLAB目前没有像PyTorch那样一行调用attention模块的现成接口但可以通过自定义层来实现。自定义层的思路是继承nnet.layer.Layer在predict方法里写前向计算逻辑在backward方法里写梯度计算。对初学者来说不建议一上来就自己写可以先尝试使用MATLAB File Exchange上的现成实现或者用更朴素的加权方法在最后一层卷积输出后面对特征图各通道计算全局平均池化再通过一个小全连接层生成通道权重再乘回原特征图。我觉得处理实际问题时不用非得追求“用了注意力机制”这个形式像SENet这种通道注意力本质上是对“哪些通道更重要”做学习。如果你发现当前模型在类别相近的情况下容易混淆加上通道注意力通常能带来直观的准确率提升。7.3 迁移学习是另一个加速通道如果你的任务不是MNIST这种简单数据集而是医学影像、自然图像分类数据量又不充裕我强烈建议先用迁移学习。MATLAB加载预训练模型特别方便net resnet18;加载后查看网络层结构替换最后几个分类层lgraph layerGraph(net); numClasses 5; newLayers [ fullyConnectedLayer(numClasses, Name, fc_new) softmaxLayer(Name, softmax_new) classificationLayer(Name, output_new)]; lgraph replaceLayer(lgraph, fc1000, newLayers(1)); lgraph replaceLayer(lgraph, ClassificationLayer_predictions, newLayers(3));这里的层名可能随版本不同略有差异建议先用analyzeNetwork(net)看清楚再替换。迁移学习时InitialLearnRate要调小我用0.0003左右比较稳定否则很容易破坏预训练模型已经学好的特征。如果你的图是灰度图预训练模型的输入层默认是3通道需要先把单通道图复制成三通道rgbImage repmat(grayImage, [1 1 3]);在augmentedImageDatastore里ColorPreprocessing也可以配置成gray2rgb会更省事。最后说句实在的。在MATLAB里做卷积神经网络最核心的优势是调试链路短、工具箱完整尤其适合已经在用MATLAB做数据处理的人。我自己的体会是先把一个小网络从数据到训练再到评估完整跑通比一开始就追求大模型、注意力机制这些花活重要得多。遇到问题就先看训练曲线再算特征图尺寸绝大多数坑都能自己排查出来。这套流程跑熟了后面无论是换成1D CNN处理信号还是通过迁移学习换到更大的数据集都是顺着这个骨架去扩展不会太费劲。本文还有配套的精品资源点击获取