简介:这份资源聚焦一维卷积神经网络(1D-CNN)的MATLAB实现,面向具备一定深度学习基础、希望处理时间序列、音频信号或文本等一维数据的学习者与开发者。内容围绕1D-CNN的基本网络结构展开,涵盖输入层、卷积层、池化层、全连接输出层以及softmax分类层的搭建思路,并给出可直接运行的MATLAB代码示例,帮助读者理解滤波器滑动提取局部特征、池化下采样与多组卷积堆叠的完整流程。压缩包内共1个文件,为m脚本源码,整体约2KB,体积轻量,便于快速导入MATLAB Deep Learning Toolbox进行调试与二次修改。该资源已有4669人学习下载,适合作为入门1D-CNN网络搭建、参数调整与分类任务验证的参考脚本,读者可据此掌握从定义层结构到训练、预测与准确率评估的完整实现路径。
1. 一维卷积不是二维卷积的降级版,它是另一条技术路线
很多人第一次接触 1D-CNN,是在做轴承振动、心电信号或者工业传感器时序分类的时候。打开 MATLAB 想找个例子,结果发现 Deep Learning Toolbox 里翻来覆去都是图像分类的 2D 卷积,于是顺手把一维信号 reshape 成 N×1 的“假图像”塞进二维网络。跑是能跑,但训练慢、参数多、还容易过拟合。问题不在 MATLAB,在于没搞清楚一维卷积到底在卷什么。
一维卷积的卷积核只沿一个方向滑动,输入通常是C×T(通道×时间步)或T×C,输出是特征图。它天生适合处理振动波形、ECG、语音帧、IMU 序列这类等间隔采样数据。相比 LSTM,它没有循环结构,训练可以完全并行;相比 Transformer,它参数量小、对样本量要求低,在几千条样本的工业场景里往往更稳。这篇就按“理论—数据—建模—训练—排错—落地”的顺序,把 MATLAB 里从零搭一个 1D-CNN 的完整路径讲清楚,适合已经会 MATLAB 基础语法、想切入深度学习但不想被 Python 环境折腾的工程师。
2. 一维卷积在 MATLAB 里的数据组织与网络层选型
2.1 输入维度到底该是 C×T 还是 T×C
MATLAB 的convolution1dLayer对输入维度有明确要求。对于序列输入,官方推荐的数据布局是C×T×N,其中 C 是通道数(特征数),T 是时间步,N 是样本数。如果你手上是一张N×T的矩阵,每个样本一行,那必须先转置再 reshape。
% 假设 rawData 是 N×T 的 double 矩阵,N 个样本,每个样本 T 个时间点 % labels 是 N×1 的 categorical 标签 T = size(rawData, 2); N = size(rawData, 1); % 转成 1×T×N,单通道 X = reshape(rawData', [1, T, N]); % 如果是多通道,比如三轴加速度,rawData 是 N×T×3 % 先 permute 成 T×3×N,再 permute 成 3×T×N % X = permute(rawData, [2 3 1]); % 得到 T×3×N % X = permute(X, [2 1 3]); % 得到 3×T×N逻辑说明:reshape是按列优先填充的,直接对rawData'做 reshape 能保证每个样本的时间序列连续排列。参数上,第一个维度 1 表示单通道,如果你有多个传感器通道,就改成对应通道数。注意不要用squeeze把单通道维度压掉,convolution1dLayer需要显式通道维。
2.2 convolution1dLayer 的关键参数怎么设
convolution1dLayer的核心参数只有四个:filterSize、numFilters、stride、padding。它们直接决定感受野和计算量。
| 参数 | 含义 | 常用取值 | 影响 |
|---|---|---|---|
| filterSize | 卷积核长度 | 3、5、7、9 | 越大感受野越宽,但参数增多 |
| numFilters | 输出通道数 | 16、32、64 | 越大特征越丰富,易过拟合 |
| stride | 滑动步长 | 1、2 | 大于 1 可降采样,减少时间步 |
| padding | 边界填充 | 'same'、'causal' | 'same' 保持长度,'causal' 防未来信息泄漏 |
layers = [ sequenceInputLayer(1, 'Name', 'input') convolution1dLayer(5, 16, 'Padding', 'same', 'Name', 'conv1') batchNormalizationLayer('Name', 'bn1') reluLayer('Name', 'relu1') maxPooling1dLayer(2, 'Stride', 2, 'Name', 'pool1') convolution1dLayer(3, 32, 'Padding', 'same', 'Name', 'conv2') batchNormalizationLayer('Name', 'bn2') reluLayer('Name', 'relu2') globalAveragePooling1dLayer('Name', 'gap') fullyConnectedLayer(4, 'Name', 'fc') softmaxLayer('Name', 'softmax') classificationLayer('Name', 'output') ];逻辑说明:第一层sequenceInputLayer(1)对应单通道输入。convolution1dLayer(5,16)表示核长 5、输出 16 通道。Padding','same'让输出时间步与输入一致,避免边缘信息被反复丢弃。maxPooling1dLayer(2,'Stride',2)把时间步减半,降低后续计算量。globalAveragePooling1dLayer替代展平层,能显著减少全连接层参数,对样本量不大的场景更友好。
提示:如果做的是因果预测(比如用过去预测未来),卷积层和池化层都要设
'causal'或确保不看到未来时间步,否则离线评估会虚高。
2.3 用 trainingOptions 控制训练节奏
训练参数里最容易踩坑的是MiniBatchSize和InitialLearnRate。一维序列样本通常比图像小,batch 可以设大一点,但学习率不能照搬图像那套。
options = trainingOptions('adam', ... 'MiniBatchSize', 64, ... 'MaxEpochs', 60, ... 'InitialLearnRate', 1e-3, ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropFactor', 0.5, ... 'LearnRateDropPeriod', 20, ... 'Shuffle', 'every-epoch', ... 'ValidationData', {XVal, YVal}, ... 'ValidationFrequency', 30, ... 'Plots', 'training-progress', ... 'Verbose', false);逻辑说明:adam对一维卷积的初始学习率不敏感,1e-3 是安全起点。piecewise配合DropFactor=0.5、DropPeriod=20,每 20 轮学习率减半,防止后期震荡。Shuffle','every-epoch'对时序分类很重要,能打乱样本顺序但不会打乱每个样本内部的时间步。ValidationData必须和训练数据同布局,否则会报维度不匹配。
3. 从原始信号到可训练网络的完整 MATLAB 实现
3.1 构造一个可复现的振动信号数据集
没有真实数据时,用合成信号验证网络结构是最快的方式。下面生成四类不同频率成分的振动信号,每类 300 个样本,每个样本 1024 个时间点。
rng(42); fs = 1024; T = 1024; N = 300; numClasses = 4; X = zeros(1, T, N*numClasses); Y = categorical(zeros(N*numClasses, 1)); for c = 1:numClasses for i = 1:N t = (0:T-1) / fs; baseFreq = 20 + c*15; sig = sin(2*pi*baseFreq*t) + 0.5*sin(2*pi*(baseFreq*2)*t); sig = sig + 0.3*randn(1, T); idx = (c-1)*N + i; X(1, :, idx) = sig; Y(idx) = categorical(c); end end % 划分训练集和验证集 idxTrain = 1:round(0.8*N*numClasses); idxVal = setdiff(1:N*numClasses, idxTrain); XTrain = X(:, :, idxTrain); YTrain = Y(idxTrain); XVal = X(:, :, idxVal); YVal = Y(idxVal);逻辑说明:rng(42)固定随机种子,保证每次生成的数据一致。每类信号由基频和二次谐波叠加,再加高斯噪声,模拟真实振动中的工频与倍频成分。X的维度是1×1024×1200,符合C×T×N布局。划分时按索引切分,避免用cvpartition打乱后还要重新对齐维度。
3.2 训练网络并读取混淆矩阵
把第 2 章的 layers 和 options 接上,直接调用trainNetwork。
net = trainNetwork(XTrain, YTrain, layers, options); % 在验证集上预测 YPred = classify(net, XVal); acc = mean(YPred == YVal); fprintf('Validation accuracy: %.2f%%\n', acc*100); % 混淆矩阵 figure; confusionchart(YVal, YPred); title('1D-CNN Validation Confusion Matrix');逻辑说明:trainNetwork会自动检测输入是序列数据,不需要额外指定。classify返回 categorical 预测标签。混淆矩阵能看出哪两类容易混,如果某两类互相误判严重,通常是它们的频率成分太接近,需要加长卷积核或增加通道数。
3.3 用 analyzeNetwork 检查层间维度
网络搭完先别急着训练,用analyzeNetwork(net)或analyzeNetwork(layers)看一眼每层输出维度。常见错误是池化层把时间步压到 0 或者全连接层输入维度对不上。
analyzeNetwork(layers)如果报错说某层输出为负或零,检查maxPooling1dLayer的池化窗口是否大于当前时间步。比如经过两次 stride=2 的池化后,1024 会变成 256,再变 128,不会出问题;但如果初始 T 只有 10,两次池化后就只剩 2,再加池化就崩了。
注意:MATLAB 2023 之后的版本对中文注释和路径更敏感,如果脚本里含中文注释且保存为 GBK,换到 UTF-8 环境可能乱码。建议统一用
feature('DefaultCharacterSet','UTF-8')或在编辑器里另存为 UTF-8。
4. 一维卷积训练中的典型故障与参数排查
4.1 损失不下降:先查数据布局再查学习率
训练时Loss一直卡在 1.38 左右(四分类的随机水平),最常见的原因是数据布局错了。sequenceInputLayer(1)期望C×T×N,如果你传了N×T×1,MATLAB 可能不报错但把样本数当成了通道数。
排查步骤:
- 在
trainNetwork前打印size(XTrain),确认是1×T×N。 - 用
XTrain(1,:,1)画一条曲线,看是不是原始信号形状。 - 如果布局对但损失不降,把
InitialLearnRate降到 1e-4 再试。 - 检查标签是不是 categorical,用
summary(YTrain)确认类别数。
% 快速检查数据布局 assert(ndims(XTrain) == 3, 'XTrain must be 3-D'); assert(size(XTrain,1) == 1, 'First dim should be channels'); assert(size(XTrain,3) == numel(YTrain), 'Sample count mismatch');4.2 验证集准确率远低于训练集:过拟合的四个刹车
一维卷积在小样本上很容易过拟合。如果训练集 99%、验证集 70%,按下面顺序加刹车:
| 手段 | 实现方式 | 适用场景 |
|---|---|---|
| Dropout | 在池化后加 dropoutLayer(0.3) | 全连接层参数过多 |
| 权重衰减 | trainingOptions 设 L2Regularization=1e-4 | 整体过拟合 |
| 早停 | ValidationPatience=10 | 验证损失回升 |
| 减小模型 | 减少 numFilters 或去掉一层卷积 | 样本量 < 2000 |
% 在 globalAveragePooling1dLayer 前插入 dropout layers = [ sequenceInputLayer(1) convolution1dLayer(5, 16, 'Padding', 'same') batchNormalizationLayer reluLayer maxPooling1dLayer(2, 'Stride', 2) convolution1dLayer(3, 32, 'Padding', 'same') batchNormalizationLayer reluLayer dropoutLayer(0.3) globalAveragePooling1dLayer fullyConnectedLayer(4) softmaxLayer classificationLayer ];逻辑说明:dropoutLayer(0.3)在训练时随机丢弃 30% 神经元,推理时自动关闭。放在全局池化前比放在全连接后更有效,因为卷积层特征图数量多,丢弃部分通道相当于做特征级正则。
4.3 训练速度慢:用 minibatchqueue 和 GPU 加速
如果数据量大、CPU 训练一轮要几分钟,优先用 GPU。MATLAB 会自动把trainNetwork放到可用 GPU 上,但数据预处理如果还在 CPU 上做,会成为瓶颈。
% 检查 GPU 可用性 canUseGPU = canUseGPU(); disp(['GPU available: ', num2str(canUseGPU)]); % 把数据转成 dlarray 并用 minibatchqueue 管理 dsXTrain = arrayDatastore(XTrain, 'IterationDimension', 3); dsYTrain = arrayDatastore(YTrain); dsTrain = combine(dsXTrain, dsYTrain); mbq = minibatchqueue(dsTrain, ... 'MiniBatchSize', 64, ... 'MiniBatchFormat', {'CBT', 'C'}, ... 'OutputEnvironment', 'auto');逻辑说明:MiniBatchFormat里'CBT'对应通道×batch×时间,这是dlarray的格式约定,和trainNetwork直接吃数组的布局不同。OutputEnvironment','auto'会在有 GPU 时自动放 GPU。用minibatchqueue后需要自定义训练循环,适合需要精细控制梯度裁剪或混合精度的场景。
5. 把 1D-CNN 用到真实传感器数据上的三个技巧
5.1 用连续小波变换做前端特征增强
原始振动信号直接进卷积层,网络需要自己学滤波。如果样本量不大,可以先做 CWT 把一维信号变成时频图,再用 2D 卷积,但那就不是 1D-CNN 了。保持一维结构又想增强特征,可以在输入层后加一个固定权重的卷积层模拟带通滤波。
% 设计一个 Morlet 小波卷积核作为初始化 fb = cwtfilterbank('SignalLength', 1024, 'SamplingFrequency', 1024, ... 'Wavelet', 'amor', 'VoicesPerOctave', 8); psi = cwtfilters2array(fb); % psi 的维度是 1024×1024,取前 16 个尺度作为卷积核 initKernel = psi(:, 1:16);逻辑说明:cwtfilterbank生成的小波滤波器组本身就是一组带通滤波器,把它作为convolution1dLayer的权重初始化,相当于给网络一个物理先验。注意这需要自定义层或手动设置Weights属性,MATLAB 原生层不直接支持,常见做法是用dlnetwork加自定义层实现。
5.2 多通道输入的通道融合顺序
三轴加速度计的数据是3×T×N。第一层卷积的numFilters不要设太小,否则三个轴的融合不充分。经验值是numFilters至少是通道数的 4 倍。
% 三通道输入 layers = [ sequenceInputLayer(3) convolution1dLayer(7, 32, 'Padding', 'same') % 32 = 3*10 左右 batchNormalizationLayer reluLayer maxPooling1dLayer(2, 'Stride', 2) convolution1dLayer(5, 64, 'Padding', 'same') batchNormalizationLayer reluLayer globalAveragePooling1dLayer fullyConnectedLayer(6) softmaxLayer classificationLayer ];逻辑说明:第一层filterSize=7比单通道时大,因为三轴信号需要更长的窗口才能捕捉到轴间相位差。numFilters=32给每个轴分配约 10 个滤波器,保证融合前各轴特征都被充分提取。
5.3 用 t-SNE 看卷积特征到底学到了什么
训练完的网络,把globalAveragePooling1dLayer的输出提取出来,用 t-SNE 降到二维,能直观判断网络是否真的把不同类别分开了。
% 提取池化层特征 featureLayer = 'gap'; features = activations(net, XVal, featureLayer, 'OutputAs', 'rows'); % t-SNE 降维 rng(1); Y2 = tsne(features, 'NumDimensions', 2, 'Perplexity', 30); % 按真实标签着色 figure; gscatter(Y2(:,1), Y2(:,2), YVal); title('t-SNE of 1D-CNN Features'); xlabel('Dimension 1'); ylabel('Dimension 2');逻辑说明:activations的OutputAs','rows'把每个样本的特征拉成一行。tsne的Perplexity一般设 5 到 50 之间,样本少就调小。如果 t-SNE 图上各类混在一起,说明网络没学到判别性特征,回去检查数据标签是否错位,或者增加卷积层深度。如果分得很开但验证准确率不高,可能是验证集分布和训练集不一致。
本文还有配套的精品资源,点击获取