尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

MATLAB一维卷积实战:从振动信号到心电波形的1D-CNN落地指南

MATLAB一维卷积实战:从振动信号到心电波形的1D-CNN落地指南 简介这份资源面向深度学习入门者与信号处理方向的开发者聚焦一维卷积神经网络1D-CNN在MATLAB中的实现帮助读者理解如何用卷积、池化与全连接层搭建处理时间序列、音频或文本等一维数据的分类网络。压缩包为rar格式仅含1个m文件体积约2KB属于轻量级源码脚本可直接在MATLAB中打开阅读与调试。资源围绕sequenceInputLayer、convolution1dLayer、maxPooling1dLayer、softmaxLayer等核心层展开完整呈现从输入层、卷积层、池化层到输出层的网络结构定义并涉及trainNetwork训练、classify预测与准确率评估等关键流程便于读者对照代码理解滤波器、池化窗口、步长等参数的作用。目前已有4670人学习下载适合希望快速上手MATLAB Deep Learning Toolbox、掌握1D-CNN基本搭建思路的读者参考。1. 一维卷积在 MATLAB 里到底能干什么从振动信号到心电波形的一条落地路径手里只有一段按时间采样的序列采样率固定、通道数不多、标签还得靠人工标这种场景下把二维 CNN 那套图像思路直接搬过来十有八九会翻车。一维卷积1D-CNN处理的正是这类数据轴承振动、心电波形、电机电流、光谱曲线、传感器时序。它的卷积核只沿时间轴滑动参数量比 2D 少一个量级在 MATLAB 里用 Deep Learning Toolbox 就能从零搭起来不需要额外装框架。这篇笔记锁定的就是「CNN0926_一维卷积_matlab1D-CNN」这个方向讲清楚一维卷积和二维卷积的本质差别、在 MATLAB 里怎么把原始信号喂进网络、卷积核和池化窗口这些参数怎么定、训练不收敛时先看哪里。适合已经会用 MATLAB 做信号处理、想把手里的时序数据接上深度学习模型的工程师也适合刚接触 cnn 基础、想找一个能跑通的最小闭环的人。下面按「先立住原理、再动手复现、最后排坑」的顺序推。2. 一维卷积和二维卷积差在哪卷积核沿哪个轴滑动决定了你的数据怎么摆2.1 从卷积核滑动方向理解 1D-CNN 的输入形状二维卷积的卷积核在高度和宽度两个方向上滑动输入是H×W×C的图像张量。一维卷积的核只在一个方向上滑动输入是L×C的序列L是时间步长度C是通道数。这个差别直接决定了 MATLAB 里sequenceInputLayer和imageInputLayer不能互换。拿一段轴承振动信号举例采样率 12 kHz取 0.5 秒就是 6000 个点单通道。如果直接把这 6000 点当成一个样本输入层写sequenceInputLayer(1)后面的convolution1dLayer的卷积核只沿这 6000 个时间点滑动。卷积核大小设 16意味着每次看 16 个连续采样点步长 1 滑过去输出还是一个序列只是长度变了。这里有个容易被忽略的点一维卷积的「通道」维度和二维卷积的「通道」维度含义不同。二维里通道是 RGB 或特征图一维里通道可以是多轴传感器的轴数也可以是多路信号。如果你有 X、Y、Z 三轴振动输入就是sequenceInputLayer(3)卷积核在时间轴上滑三个通道同时参与计算。提示MATLAB 的convolution1dLayer默认Padding是same输出长度和输入一致设成causal则只依赖当前及之前的时间步做在线预测时必须用这个。2.2 为什么时序任务里 1D-CNN 常常比 LSTM 更先被试不是 1D-CNN 一定比 LSTM 强而是在样本量不大、模式偏局部的情况下1D-CNN 往往更快出结果。原因有三条。第一局部感受野匹配局部模式。轴承故障的冲击成分、心电的 QRS 波群都是短时间窗口内的固定形状卷积核学的就是这个形状不需要像 LSTM 那样靠门控去记长程依赖。第二参数少、训练快。一个kernelSize16, numFilters32的卷积层参数量是16×1×3232几百个参数。同样输入长度下 LSTM 的参数量是它的几十倍小数据集上更容易过拟合。第三MATLAB 里 1D-CNN 的调试链路短。trainingProgressMonitor能实时看准确率和损失analyzeNetwork能直接看每层输出尺寸不用像搭 LSTM 那样反复调sequenceLength和OutputMode。常见做法是先跑一个 3 层卷积 全局池化 全连接的 1D-CNN 当基线如果准确率卡住再考虑加 LSTM 层做混合。我一般会先把这个基线跑通再决定要不要上更复杂的结构。2.3 在 MATLAB 里搭一个最小 1D-CNN 的完整代码下面这段代码是一个能直接跑的最小闭环用随机生成的两类时序信号做二分类目的是让你先确认环境能跑通再换成自己的数据。% 生成两类合成时序信号一类是低频正弦一类是高频正弦加噪声 rng(0); fs 1000; % 采样率 1000 Hz t (0:1/fs:0.5-1/fs); % 0.5 秒500 个点 numSamples 400; % 总样本数 X zeros(500, 1, 1, numSamples); % 序列长度×通道×1×样本数 Y categorical(zeros(numSamples, 1)); for i 1:numSamples if mod(i, 2) 1 % 类别 1低频 10 Hz 正弦 X(:,1,1,i) sin(2*pi*10*t) 0.1*randn(size(t)); Y(i) low; else % 类别 2高频 80 Hz 正弦加噪声 X(:,1,1,i) sin(2*pi*80*t) 0.3*randn(size(t)); Y(i) high; end end % 划分训练集和验证集 idx randperm(numSamples); numTrain round(0.8 * numSamples); XTrain X(:,:,:,idx(1:numTrain)); YTrain Y(idx(1:numTrain)); XVal X(:,:,:,idx(numTrain1:end)); YVal Y(idx(numTrain1:end)); % 定义 1D-CNN 网络 layers [ sequenceInputLayer(1, Name, input) convolution1dLayer(16, 32, Padding, same, Name, conv1) batchNormalizationLayer(Name, bn1) reluLayer(Name, relu1) maxPooling1dLayer(2, Stride, 2, Name, pool1) convolution1dLayer(8, 64, Padding, same, Name, conv2) batchNormalizationLayer(Name, bn2) reluLayer(Name, relu2) globalAveragePooling1dLayer(Name, gap) fullyConnectedLayer(2, Name, fc) softmaxLayer(Name, softmax) classificationLayer(Name, output) ]; % 训练选项 options trainingOptions(adam, ... MaxEpochs, 30, ... MiniBatchSize, 32, ... ValidationData, {XVal, YVal}, ... ValidationFrequency, 10, ... InitialLearnRate, 1e-3, ... Plots, training-progress, ... Verbose, false); % 训练网络 net trainNetwork(XTrain, YTrain, layers, options);逻辑说明sequenceInputLayer(1)声明输入是单通道序列长度不固定MATLAB 会自动按 batch 处理。convolution1dLayer(16, 32)的第一个参数是卷积核大小第二个是滤波器数量Paddingsame保证输出长度和输入一致。maxPooling1dLayer(2, Stride, 2)把序列长度减半降低计算量。globalAveragePooling1dLayer把整个时间轴压成一个向量替代展平层参数量更少对小数据集更友好。参数说明MiniBatchSize设 32 是常见起点样本少于 200 时降到 16。InitialLearnRate设 1e-3如果损失震荡就降到 1e-4。MaxEpochs设 30 是保守值看验证集准确率不再上升就可以停。注意X的维度顺序是序列长度×通道数×1×样本数第四个维度是样本数这个顺序在trainNetwork里是固定的搞错会报维度不匹配。3. 把真实信号喂进 1D-CNN数据预处理和输入层参数怎么定3.1 原始振动信号到网络输入的四个步骤真实信号不会像合成信号那么干净从原始数据到能训练的输入中间有四步必须做。第一步分帧。一段长信号要切成固定长度的样本。比如 10 秒振动信号采样率 12 kHz切成 0.5 秒一段每段 6000 点得到 20 个样本。切的时候用滑动窗口重叠率 50% 可以增加样本数但要注意同一段信号切出来的样本不能同时出现在训练集和验证集否则验证准确率会虚高。第二步去均值。每个样本减去自己的均值消除传感器零点漂移。用X X - mean(X, 1)按时间轴做。第三步归一化。把幅值缩放到 [-1, 1] 或 [0, 1]。常见做法是除以该样本的最大绝对值或者用整个训练集的均值和标准差做 z-score。注意归一化参数只能用训练集算验证集和测试集用同一套参数。第四步转成 MATLAB 要求的维度。sequenceInputLayer接受的数据格式是L×C×1×NL是序列长度C是通道数N是样本数。如果你的数据是N×L的矩阵需要permute一下。% 假设 rawData 是 N×L 的矩阵N 个样本每个 L 个点 N size(rawData, 1); L size(rawData, 2); % 去均值 rawData rawData - mean(rawData, 2); % 按样本归一化到 [-1, 1] maxAbs max(abs(rawData), [], 2); rawData rawData ./ maxAbs; % 转成 L×1×1×N X permute(rawData, [2, 3, 4, 1]);逻辑说明mean(rawData, 2)按行求均值每行是一个样本。max(abs(rawData), [], 2)找每行最大绝对值。permute把N×L变成L×1×1×N这是sequenceInputLayer要求的顺序。参数说明重叠率一般取 0 到 50%样本少的时候用 50%样本多的时候用 0 减少冗余。归一化方式选按样本还是按数据集取决于信号幅值是否稳定幅值波动大就按样本归一化。3.2 卷积核大小、滤波器数量、池化窗口的取值逻辑这三个参数是 1D-CNN 里最需要调的取值不是拍脑袋有对应的物理含义。卷积核大小决定每次看多长的时间窗口。如果故障特征是一个持续 5 ms 的冲击采样率 12 kHz对应 60 个点卷积核大小就应该在 60 附近设 32 或 64。设太小看不到完整冲击设太大引入无关噪声。常见范围是 8 到 64。滤波器数量决定能提取多少种不同的局部模式。第一层一般设 16 到 64后面层翻倍。滤波器太少欠拟合太多过拟合且训练慢。小数据集少于 1000 样本第一层设 16 或 32 就够。池化窗口决定降采样倍数。窗口 2、步长 2 是最常见的序列长度减半。如果序列很长超过 10000 点可以用窗口 4 或 8 加速。但池化太激进会丢失时间分辨率最后一层池化后序列长度最好不低于 10。参数常见取值取值依据调大后果调小后果卷积核大小8 / 16 / 32 / 64匹配特征持续时间引入无关噪声看不到完整模式滤波器数量16 / 32 / 64 / 128模式种类多少过拟合、训练慢欠拟合池化窗口2 / 4 / 8序列长度和计算量丢失时间分辨率计算量大步长1 / 2是否降采样输出长度缩短输出长度不变提示用analyzeNetwork(net)可以看到每一层输出的实际尺寸调参前先跑一遍确认序列长度在每层之后的变化符合预期。3.3 用真实数据替换合成数据的接入点把第 2 章的代码改成用真实数据只需要替换数据加载和预处理部分网络结构和训练选项基本不动。% 从 MAT 文件加载真实信号假设文件里有 data 和 label 两个变量 load(bearing_data.mat); % data: N×L, label: N×1 % 预处理 data data - mean(data, 2); maxAbs max(abs(data), [], 2); data data ./ maxAbs; % 转维度 X permute(data, [2, 3, 4, 1]); Y categorical(label); % 划分数据集注意同一段信号切出来的样本要分到同一集合 rng(42); idx randperm(size(X, 4)); numTrain round(0.7 * size(X, 4)); numVal round(0.15 * size(X, 4)); XTrain X(:,:,:,idx(1:numTrain)); YTrain Y(idx(1:numTrain)); XVal X(:,:,:,idx(numTrain1:numTrainnumVal)); YVal Y(idx(numTrain1:numTrainnumVal)); XTest X(:,:,:,idx(numTrainnumVal1:end)); YTest Y(idx(numTrainnumVal1:end)); % 后续网络定义和训练与第 2 章一致逻辑说明load加载数据后预处理和维度转换与合成数据完全一样。关键是划分数据集时如果样本来自同一段长信号的滑动窗口要按信号段划分而不是按样本随机划分否则验证集里会有和训练集高度重叠的样本。参数说明训练集 70%、验证集 15%、测试集 15% 是常见比例。样本少于 500 时可以用 80/20 只分训练和验证测试集从验证集里再切。4. 训练不收敛、准确率卡住、验证集虚高1D-CNN 排查清单4.1 损失不下降的三种典型原因现象训练开始后损失一直在 2.3 附近二分类的随机水平准确率 50% 不动。原因一学习率太大。Adam 默认 1e-3如果信号幅值没归一化梯度会爆炸。解决先确认输入已经归一化到 [-1, 1]再把InitialLearnRate降到 1e-4。原因二输入维度搞错。sequenceInputLayer(1)但数据是L×3×1×N通道数对不上网络实际在学噪声。解决用size(X)确认维度通道数和sequenceInputLayer的参数一致。原因三标签没转成 categorical。trainNetwork要求分类标签是categorical类型如果是数值 0/1会被当成回归任务。解决Y categorical(Y)。4.2 验证集准确率比训练集还高的排查现象训练集准确率 85%验证集 92%。原因数据泄漏。同一段信号切出来的样本同时出现在训练集和验证集验证集里的样本和训练集高度相似。解决按原始信号段划分数据集同一段信号的所有窗口只进一个集合。另一个可能原因是验证集太小统计波动大。验证集样本少于 50 时准确率波动几个百分点很正常。解决增大验证集比例或者用交叉验证。4.3 过拟合的四个信号和对应处理现象训练集准确率 99%验证集 70% 且不再上升。信号一训练损失持续下降但验证损失开始上升。处理加dropoutLayer(0.5)在全局池化之后。信号二滤波器数量太多。处理第一层从 64 降到 32 或 16。信号三样本太少。处理加数据增强对时序信号可以做加噪声、时间偏移、幅值缩放。信号四训练轮数太多。处理用ValidationPatience设 5验证损失 5 轮不降就停。% 在 layers 里加入 dropout 和早停 layers [ sequenceInputLayer(1) convolution1dLayer(16, 32, Padding, same) batchNormalizationLayer reluLayer maxPooling1dLayer(2, Stride, 2) convolution1dLayer(8, 64, Padding, same) batchNormalizationLayer reluLayer globalAveragePooling1dLayer dropoutLayer(0.5) % 加 dropout fullyConnectedLayer(2) softmaxLayer classificationLayer ]; options trainingOptions(adam, ... MaxEpochs, 50, ... MiniBatchSize, 32, ... ValidationData, {XVal, YVal}, ... ValidationPatience, 5, ... % 早停 InitialLearnRate, 1e-3, ... Plots, training-progress, ... Verbose, false);逻辑说明dropoutLayer(0.5)在训练时随机丢弃一半神经元强制网络不依赖特定路径。ValidationPatience设 5 表示验证损失连续 5 轮不下降就停止训练防止过拟合。参数说明dropout 比例 0.3 到 0.5 是常见范围样本越少比例越高。ValidationPatience设 5 到 10太小会早停太大起不到作用。4.4 MATLAB 版本和中文注释的坑现象代码在别人机器上跑报错或者中文注释显示乱码。原因一MATLAB 版本差异。convolution1dLayer在 R2019b 之后才支持trainingProgressMonitor在 R2020a 之后才有。解决确认版本老版本用trainNetwork的Plots参数替代。原因二中文注释乱码。MATLAB 默认编码在 Windows 上是 GBKLinux 和 Mac 上是 UTF-8跨平台打开会乱码。解决脚本文件统一存成 UTF-8在 MATLAB 里用feature(DefaultCharacterSet, UTF-8)设置。原因三globalAveragePooling1dLayer在 R2021b 之前叫globalAveragePooling1dLayer老版本可能没有。解决用fullyConnectedLayer前加flattenLayer替代但参数量会增加。注意如果报错信息里出现Undefined function convolution1dLayer先查版本不要急着改代码。5. 把 1D-CNN 用到自己数据上的三个进阶技巧5.1 用dlnetwork自定义训练循环做在线预测trainNetwork适合离线批量训练但如果要做在线预测或者自定义损失函数需要用dlnetwork和dlarray。下面是一个最小示例展示怎么把训练好的网络转成dlnetwork并对单样本做预测。% 把训练好的 net 转成 dlnetwork dlnet dlnetwork(net); % 对单个样本做预测 x XTest(:,:,:,1); % 取一个测试样本 dlX dlarray(x, SSCB); % S序列, C通道, Bbatch scores predict(dlnet, dlX); [~, predLabel] max(extractdata(scores));逻辑说明dlarray的维度标签SSCB对应序列、通道、单例、batch。predict只做前向传播不计算梯度适合部署。extractdata把dlarray转回普通数组。参数说明SSCB里的S是 spatial序列C是 channelB是 batch。如果输入是多通道C对应通道数。5.2 用analyzeNetwork和activations看网络学到了什么训练完不是结束要知道网络在看哪个时间段。用activations提取中间层输出可以看到卷积层对哪些时间点响应强。% 提取第一个卷积层的输出 layerName conv1; act activations(net, XTest, layerName); % act 的维度是 L×numFilters×1×N % 对第一个样本看每个滤波器的响应 sampleAct act(:,:,1,1); meanResponse mean(abs(sampleAct), 2); % 按时间轴平均 % 画出来 figure; plot(meanResponse); xlabel(时间步); ylabel(平均激活幅值); title(第一层卷积对时间点的响应强度);逻辑说明activations返回指定层的输出。对第一个卷积层输出维度是序列长度×滤波器数量×1×样本数。按时间轴平均后峰值位置就是网络关注的时间段。参数说明layerName要填layers里定义的Name没定义的话用默认名。mean(abs(...), 2)按时间轴求平均得到每个时间点的平均响应。5.3 迁移到新数据集时的三个检查点换一个新数据集时不要从头调参先做三个检查。检查一输入长度是否一致。新数据切出来的样本长度和原网络输入长度不同sequenceInputLayer不限制长度但池化层会改变长度最后一层池化后长度不能小于 1。解决用analyzeNetwork确认。检查二类别数是否变化。fullyConnectedLayer的输出维度要改成新类别数classificationLayer会自动适配。检查三归一化方式是否一致。新数据的幅值范围如果和训练数据差很多要用训练集的均值和标准差做归一化不能重新算。我自己的习惯是每换一个数据集先把analyzeNetwork跑一遍确认每层输出尺寸再跑 5 个 epoch 看损失有没有下降最后才调参。这个顺序能省掉很多来回改代码的时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表