基于STFT-CNN-BiGRU的故障诊断方法及Matlab实现

发布时间:2026/10/22 16:52:48
基于STFT-CNN-BiGRU的故障诊断方法及Matlab实现 搞故障诊断这些年我最大的感触是很多设备“病”了传感器信号早就给了提示但传统方法就是看不出来。尤其像齿轮箱、轴承这类旋转机械振动信号里埋着大量非平稳的冲击成分常规的频谱分析一平均就把关键信息给抹平了。后来我把短时傅里叶变换STFT、卷积神经网络CNN和双向门控循环单元BiGRU串成一条完整的处理链条用Matlab搭了一套故障诊断流程实测下来比单用CNN或者单用LSTM稳定不少也更容易部署到实际的监测场景里。这篇就围绕STFT-CNN-BiGRU这条技术路线把原理、网络设计、Matlab实现和踩坑经验一次性讲清楚。适合刚接触深度学习故障诊断的初学者也适合想把手头分类模型往上提一档的工程师参考。1. 方法设计背景与整体思路1.1 为什么选STFT-CNN-BiGRU这条路线先聊聊方案选型这件事。故障诊断的核心矛盾在于故障特征在时域和频域上是耦合的而且出现的时间点往往非常短暂。拿轴承外圈点蚀来说故障特征频率确实可以算出来但实际采集到的信号里这个频率成分会和转频、啮合频率以及其他噪声混在一起如果直接对整段信号做傅里叶变换得到的是全局平均的频谱故障冲击发生的具体时刻信息就丢了。反过来只盯时域波形又很难和正常振动区分开。这就是STFT的价值所在。它把信号切成一段一段的短窗对每个窗做傅里叶变换最后拼出一张二维的时频图。横轴是时间纵轴是频率颜色深浅代表能量强弱。故障冲击会在时频图上形成一条明显的“亮带”或者“斑块”比单纯看频谱直观得多。但问题也跟着来了时频图本质上是图像想直接从里面找出故障模式靠人工设计特征不仅累而且泛化能力差。CNN天然擅长处理图像这类二维结构它能自动学习时频图里的局部纹理特征比如冲击条纹的走向、能量集中的频带范围。不过CNN有个短板它更关注空间局部特征对时间序列上的前后依赖关系理解不够。而机械故障信号恰恰是时间序列某一时刻的状态往往和前面一段时间是相关的。BiGRU正好补上这一环。双向门控循环单元能同时从前向和后向两个方向捕捉时间依赖把CNN从时频图中提取到的特征序列再“读”一遍建模故障模式随时间的演变规律。简单说就是STFT负责把信号变成“看得见”的时频图CNN负责从图里“找特征”BiGRU负责把特征按时间顺序“串起来”最后接一个分类层输出故障类型。这个三段式结构各有分工比单模型更贴合故障信号本身的特点。1.2 整体流程框架我实际跑的流程大致分五个环节数据采集与预处理用加速度传感器采集振动信号做去直流、去趋势和滑窗切片。时频变换对每个样本片段做STFT得到二维时频幅度谱转成单通道灰度图或三通道伪彩图。样本划分按故障类型打标签划分训练集、验证集和测试集注意按设备运行时间段划分避免同源数据混在一起造成评估偏差。模型训练搭建CNN-BiGRU混合网络用交叉熵损失函数训练监控训练集和验证集上的准确率与损失曲线。评估与部署用混淆矩阵、精确率、召回率评估各类故障的识别效果最后导出训练好的模型参数封装成诊断函数。这套流程里STFT的参数选择直接影响后续CNN能“看到”什么是最容易被忽略但影响最大的环节。窗口长度选短了频率分辨率差选长了时间分辨率差。这是一个权衡不结合信号特征去调参后面网络再强也白搭。我后面会专门讲这个。2. 三大核心模块原理拆解2.1 短时傅里叶变换STFT从傅里叶到时间-频率联合分析要理解STFT先得往回退一步看傅里叶变换。傅里叶变换将一段时域信号分解成不同频率分量的叠加但代价是失去了时间信息。打个比方傅里叶变换就像把一整部电影的每一帧叠加成一张照片你能看出画面里有哪些元素但完全分不清这些元素是在哪个时间段出现的。对于平稳信号这种“全局平均”没问题但对故障信号这种频率成分随时间变化的非平稳信号就远远不够了。STFT的核心操作是加窗用一个长度有限的窗函数通常是汉宁窗在时间轴上滑动把长信号切成若干短片段假设每个片段内的信号近似平稳然后对每个片段做傅里叶变换。数学上表示为X(m, k) Σ_{n0}^{N-1} x(n mH) w(n) e^{-j2πkn/N}其中 x(n) 是原始信号w(n) 是窗函数N 是窗长H 是帧移hop size。这里的两个关键参数窗长 N 和帧移 H。窗长决定频率分辨率频率分辨率 Δf Fs/N。比如采样率 Fs 为 12kHz窗长为 1024 点时Δf ≈ 11.7Hz。帧移决定时间分辨率通常取窗长的 50% 到 75% 重叠。重叠率越高时频图越平滑但计算量也越大。实际选窗长时我一般先看目标故障特征频率的大致范围。以齿轮箱啮合频率为例如果啮合频率在 1000Hz 附近那窗长要保证频率分辨率至少能区分相邻的边频带通常取 512 到 1024 点比较稳。如果只看低频的转频和轴承特征频率窗长可以适当加长。这类参数没有绝对“最优”都是针对信号特征去试出来的。另外有个细节容易踩坑STFT的输入信号如果没做去直流处理时频图的第一行会出现一条很亮的横线属于零频分量会干扰CNN的注意力。预处理阶段一定要先减去均值或者高速滤波把直流和低频漂移清掉。2.2 卷积神经网络CNN自动提取局部特征的利器CNN在图像任务上表现好靠的是“局部感受野”和“权值共享”这两个核心特性。局部感受野意味着每个卷积核只关注输入图像的一小块区域这个机制和故障时频图的特征分布吻合。故障冲击在时频图上通常只占局部的时间和频带范围不会均匀分布在整个图上。CNN的卷积核在滑动过程中可以捕捉到这些局部异常模式比如竖条状的冲击条纹、斜向的调频带而不需要人为指定特征位置。权值共享则大大减少了参数量。同样是处理一张 256×256 的时频图如果全连接网络直接展开每个神经元都要连接所有像素参数量轻松破万甚至破百万在小样本情况下极易过拟合。而CNN通过卷积核共享权重把参数量压到几百到几千的级别训练起来快也更容易收敛。在设计CNN结构时我的习惯是前几层用较小的卷积核如3×3在保持特征图尺寸的同时提取细节纹理后面几层逐步增大步长或加入池化扩大感受野并降低特征分辨率。卷积核的数量则从 32 开始逐层翻倍到 128 或 256这样网络既能提取低层纹理又能组合高层语义特征。这里有个原则核数量和层数并不是越多越好核太多会导致特征冗余层数太深在小样本数据上反而容易过拟合。故障诊断场景的数据量通常远小于ImageNet这种百万级数据集所以浅层CNN三四层卷积往往比堆到十几层更实用。2.3 双向门控循环单元BiGRU捕捉时间依赖关系CNN把时频图压缩成了一串特征向量但这串向量之间还隐藏着时间上的先后关系。比如故障从发生到加剧特征会呈现渐变趋势又比如某些瞬时冲击持续几个周期会有周期性的重复模式。这类时间依赖关系就是循环神经网络RNN的强项。传统RNN有个很头疼的问题长序列训练时容易发生梯度消失或梯度爆炸导致模型学不到远距离依赖。GRU在RNN基础上引入了两个门控机制更新门update gate和重置门reset gate。更新门决定前一时刻的隐藏状态有多少保留到当前时刻重置门决定当前候选隐藏状态有多少受前一时刻影响。这两个门的设计让信息能在序列中更长距离地传递同时保持训练稳定。LSTM和GRU功能上很像但GRU结构更精简参数更少训练速度更快。在故障诊断这种样本量不大的场景下GRU更容易收敛也不容易过拟合。BiGRU则是在GRU基础上增加了一个反向的隐藏层。常规GRU只能按时间正序“读”序列但有些故障模式的特征可能表现为在某个时间点之前有异常前兆、之后有持续衰减单向GRU只能看到前向信息对这类模式的建模能力有限。BiGRU同时处理正向和反向序列最后把两个方向的隐藏状态拼接起来相当于从未来和过去两个方向综合判断当前时刻的特征信息利用率更高。需要说明的是BiGRU虽然强大但计算量比单向GRU高不少训练时间也接近翻倍。如果你的故障信号周期性很强、前后依赖关系明显用BiGRU是值得的如果信号本身是平稳随机过程那双向带来的收益就有限。这需要结合数据实际情况做权衡不是无脑上BiGRU就更好。3. 网络架构设计与参数确定3.1 整体网络结构我使用的网络结构可以拆成三个子模块。第一个子模块是特征提取层输入是STFT时频图尺寸为 224×224×1单通道灰度图。经过三层卷积加池化第一层卷积核数量 32核大小 3×3激活函数ReLU后接2×2最大池化第二层卷积核数量 64核大小 3×3第三层卷积核数量 128核大小 3×3池化后特征图降为 28×28×128。然后把三维特征图展平成一维特征序列长度是 28×128 3584。第二个子模块是时序建模层。展平后的特征序列送入BiGRU层隐藏单元数量设为 128序列方向设置为“双向”。这里有个关键处理展平后的序列长度是 28对应原来的时间维度位置每个时间步上的特征维度是 128所以Reshape时需要保留时间维度的信息。我在Matlab里先用fullyConnectedLayer和featureInputLayer的组合来实现维度变换也可以直接用reshape函数把特征图转为序列格式。第三个子模块是分类层。BiGRU的输出经过一个全连接层映射到类别数量比如正常、内圈故障、外圈故障、滚动体故障四类接Softmax层输出概率最后用分类层classificationLayer计算交叉熵损失。整个网络的参数总量大概在百万量级对于几千条样本的数据集来说是可训练的。结构上最大的特点是CNN和BiGRU的衔接方式这地方如果没处理好信息流动会断掉。3.2 关键参数设置与计算这里我把自己实际用的参数列成表并解释每个参数为什么这么定。参数项设定值选择依据输入图像尺寸224×224与STFT频率轴点数和时间帧数对应同时兼顾训练速度卷积核尺寸3×3小卷积核叠加可获得与大卷积核相同的感受野参数更少卷积核数量32/64/128逐层翻倍在特征提取和计算量之间取平衡池化方式2×2最大池化保留显著特征降低特征图分辨率减少过拟合风险BiGRU隐藏单元128与CNN最后一层特征通道数匹配避免信息瓶颈Dropout比率0.5全连接层前加入防止依赖局部特征导致过拟合初始学习率0.001Adam优化器常用值训练后期可降为0.0001批大小32在显存和梯度稳定性之间折中训练轮数50配合早停策略实际在30轮左右收敛卷积层输出尺寸的计算公式可以记为输出尺寸 (输入尺寸 - 核尺寸 2×填充) / 步长 1比如输入 224×224核 3×3步长 1填充 1输出尺寸就是 (224-32)/11 224保持不变。池化后再减半。按这个公式手算一遍每层的输出尺寸能有效避免网络维度不匹配的报错。我在写代码前一定会先列一个“尺寸流转表”把每一层的前后维度写清楚比反复试错省事得多。3.3 训练策略与超参数选择训练这部分我踩过不少坑。最典型的就是初始学习率给太高导致损失函数在训练初期像过山车一样震荡准确率停在某个值上不去。后来我固定用小批量训练加学习率衰减前20轮学习率设为0.00120轮后每5轮乘以0.5。效果比较稳定。另一个关键策略是早停early stopping。我设置验证集损失连续5轮不下降时就停止训练并恢复最佳模型权重。原因很简单故障诊断的真实场景中验证集和训练集分布存在差异一味追求训练集准确率只会把模型带到过拟合深渊。早停相当于给训练加了一个“刹车”防止模型把训练样本的噪声都背下来。数据增强方面我试过对时频图做随机平移、加高斯噪声、小幅旋转效果有好有坏。平移和噪声增强对提升泛化能力有一点帮助但旋转增强要谨慎因为时频图的旋转会破坏时间轴和频率轴的物理意义旋转不当反而会引入错误样本。一般我只做时间方向的小幅平移和频率方向的随机遮盖遮盖比例控制在10%以内。4. Matlab实现全过程详解4.1 数据预处理与STFT时频图生成我用Matlab R2022a做实验工具箱主要用到Signal Processing Toolbox和Deep Learning Toolbox。数据是某工业现场采集的齿轮箱振动加速度信号采样率16kHz包含正常、磨损、断齿、点蚀四种状态。数据预处理的完整流程是这样的读取原始信号先去除直流分量用detrend函数去掉线性趋势项。按样本长度设为2048点对应0.128秒进行滑窗切片步长设为1024点重叠50%。对每个切片做带通滤波频带设为800Hz到6000Hz滤除低频转频干扰和高频噪声。对每个切片做STFT得到时频矩阵取幅值并转换为灰度图。STFT的核心Matlab代码可以这样写% 参数设置 fs 16000; % 采样率 16kHz windowLen 512; % 窗长度 512点约32ms noverlap 384; % 重叠点数重叠率75% nfft 512; % FFT点数 % 对单个样本信号做STFT [s, f, t] spectrogram(data, hann(windowLen), noverlap, nfft, fs); % 取幅值并转换为分贝值 s_db 20*log10(abs(s) eps); % 转为灰度图尺寸缩放为224x224 img mat2gray(s_db); img_resized imresize(img, [224, 224]);这里特别注意eps的添加。直接取对数时如果幅值为0会出现无穷大值干扰图像归一化。加上eps这个极小值可以保证数值稳定。这类细节函数文档里不会讲但调试时很关键。4.2 网络定义与训练代码网络定义部分我用layerGraph的方式组织方便修改和调试。下面是一段核心代码框架% 加载训练数据 % XTrain: 224x224x1xN 的时频图数组 % YTrain: 分类标签 % 网络结构定义 layers [ imageInputLayer([224 224 1], Name, input) convolution2dLayer(3, 32, Padding, same, Name, conv1) batchNormalizationLayer(Name, bn1) reluLayer(Name, relu1) maxPooling2dLayer(2, Stride, 2, Name, pool1) convolution2dLayer(3, 64, Padding, same, Name, conv2) batchNormalizationLayer(Name, bn2) reluLayer(Name, relu2) maxPooling2dLayer(2, Stride, 2, Name, pool2) convolution2dLayer(3, 128, Padding, same, Name, conv3) batchNormalizationLayer(Name, bn3) reluLayer(Name, relu3) maxPooling2dLayer(2, Stride, 2, Name, pool3) % 转为序列格式输入BiGRU flattenLayer(Name, flatten) fullyConnectedLayer(128, Name, fc_seq) % 这里需要reshape为序列格式sequenceInputLayer配合 bilstmLayer(128, OutputMode, last, Name, bilstm) dropoutLayer(0.5, Name, dropout) fullyConnectedLayer(4, Name, fc_out) softmaxLayer(Name, softmax) classificationLayer(Name, output) ]; lgraph layerGraph(layers);需要注意一个坑Matlab的bilstmLayer要求输入是序列格式而CNN输出的通常是特征图。需要先用flattenLayer展平再接入sequenceInputLayer或者通过reshape操作转换成序列。但这里如果直接展平成一个长向量再接BiGRU会把原来时频图的时间位置信息打乱。正确做法是在展平之前把特征图按时间维度保留下来比如把[28 28 128]的特征图重排成[28 3584]的序列格式每个时间步对应一个特征向量。Matlab里可以借助sequenceInputLayerreshape组合实现或者用自定义层来重排。我建议优先用Deep Learning Toolbox自带的sequenceInputLayer来显式声明序列输入。如果是在训练时遇到维度错误多半就是这步出了问题。调试方法是在网络定义后用analyzeNetwork(lgraph)检查每一层的数据形状它会明确告诉你哪一层不匹配。训练部分代码如下% 定义训练选项 options trainingOptions(adam, ... InitialLearnRate, 0.001, ... MaxEpochs, 50, ... MiniBatchSize, 32, ... ValidationData, {XValidation, YValidation}, ... ValidationFrequency, 20, ... LearnRateSchedule, piecewise, ... LearnRateDropPeriod, 10, ... LearnRateDropFactor, 0.5, ... Plots, training-progress, ... Verbose, true); % 训练网络 net trainNetwork(XTrain, YTrain, lgraph, options);4.3 模型评估与可视化训练完成后除了看准确率我强烈建议输出混淆矩阵和各类别精确率、召回率因为总准确率会骗人。比如数据里正常样本占90%就算把所有故障都分错准确率也有90%但实际诊断毫无价值。评估代码很简单% 测试集预测 YPred classify(net, XTest); YTrue categorical(YTest); % 混淆矩阵 cm confusionmat(YTrue, YPred); figure; confusionchart(cm, classNames); % 计算精确率和召回率 for i 1:numel(classNames) TP cm(i,i); FP sum(cm(:,i)) - TP; FN sum(cm(i,:)) - TP; precision(i) TP / (TP FP); recall(i) TP / (TP FN); end这个环节的隐藏价值在于定位“混淆在哪两类之间”。我处理过的案例里磨损和点蚀经常被混在一起原因就是这两类故障的时频图在低频段有相似的能量分布。这时候再去回看时频图有针对性地调整频带范围或者增加特征层次效果比盲目改网络结构好得多。5. 实验验证与对比分析5.1 数据说明与实验设置实验数据来自某高校机械故障模拟实验台这里隐去具体名称。采集了齿轮箱四种状态正常、齿面磨损、断齿、点蚀每种状态各获取320个样本按 0.128 秒长度切片。将每种状态的样本按 6:2:2 的比例划分为训练集、验证集和测试集总计训练样本768个验证样本256个测试样本256个。需要特别说明一点我划分数据集时是按照采集时间顺序划分的打乱之前先保证同一种状态的连续时间片段不要同时出现在训练集和测试集里。如果随机打乱后简单划分同一个时间段切割出的高度相似的样本会同时进入训练集和测试集导致评估结果虚高。这个问题在很多论文里都出现过。5.2 实验结果对比为了验证STFT-CNN-BiGRU的优劣我同时用另外三个模型做了对比单一CNN去掉BiGRU、STFT-CNN去掉BiGRU直接用CNN输出接分类、STFT-CNN-BiGRU完整模型。所有模型使用相同的数据集和预处理流程。对比结果如下表模型测试集准确率训练时间秒模型参数量单一CNN时域信号输入86.72%128约85万STFT-CNN91.41%142约80万STFT-CNN-BiGRU96.88%236约118万从结果看加入STFT带来的准确率提升比加入BiGRU更大这印证了“输入特征的质量决定了模型性能的上限”这句话。BiGRU的加入在准确率上又提升了约5个百分点说明时间依赖建模对故障分类确实有效但训练时间也相应增加了接近一倍。在资源有限的情况下STFT-CNN已经是一个不错的选择加上BiGRU更像是对精度有更高要求时的“精装修”。5.3 结果分析与讨论进一步查看各类故障的分类结果发现完整模型对断齿的识别效果最好几乎全部正确而磨损和点蚀之间依然有少量混淆。分析时频图可以发现磨损故障的时频能量分布相对分散点蚀故障则有较明显的周期性冲击边带但两者在低频区域的形态有一定的相似性。模型在这里出现判断摇摆是合理的同时也提示了一个改进方向可以在STFT基础上增加一些统计特征作为辅助输入比如谱峭度和小波包能量比让网络有更多判别信息可用。从工程角度看这个结果已经可以落地了。96.88%的准确率在四分类场景下相当可观而且模型文件大小只有几MB用普通的工控机就能跑实时推断。只要保持采样率一致测试环境中采集的信号与训练数据分布差别不大模型就能正常工作。6. 常见问题排查与经验总结6.1 典型问题速查表这节把我在复现和调试过程中遇到最多的问题整理出来按出现频率排序。问题现象可能原因解决方案训练损失不下降学习率过高或过低激活函数选择不当尝试学习率0.001配合Adam检查输入数据是否归一化过拟合训练准确率高但验证准确率低数据量不足Dropout比例低增加Dropout到0.5做数据增强缩短训练轮数时频图模糊不清窗长过短频率分辨率不足增加窗长或减少FFT点数尝试汉宁窗BiGRU维度报错展平后序列维度与BiGRU输入不匹配用analyzeNetwork检查维度确保序列时间步正确训练速度极慢BiGRU序列过长参数量大减小隐藏单元数或改用单向GRU对比效果时频图第一行有亮线信号含直流分量预处理时去均值或高速滤波6.2 实操心得与避坑经验最后聊几个文档里很难找到的经验。第一STFT的窗函数选择。我试过矩形窗、汉宁窗和海明窗发现汉宁窗在频率泄漏抑制和频率分辨率之间的平衡最好也是大多数信号处理场景的默认选择。矩形窗虽然主瓣窄但旁瓣泄漏大容易在时频图上产生假的频率带尤其是在故障冲击引起的瞬态信号上。第二CNN部分不建议一开始就用预训练模型微调。很多人习惯拿图像分类的预训练网络过来改输入层但振动时频图和自然图像差异太大预训练权重在浅层提取的纹理特征可能完全不适用。自己从零训练一个小型CNN反而更容易收敛也更好控制特征表达的内容。第三Batch Normalization层的位置需要留心。我把BN放在卷积层之后、激活函数之前效果比放在激活之后更稳定。原因是BN的作用是规范每层输入分布卷积输出后先归一化再激活能让ReLU的输入分布更集中减少死神经元出现的概率。第四BiGRU输出模式的选择。Matlab的bilstmLayer有两个常用输出模式last只输出最后一个时间步的输出sequence输出整个序列。如果做分类用last就够了计算量小很多如果后续还要接其他时序模型再用sequence模式。我第一次用sequence模式接全连接层时发现输出维度不对查了半天才反应过来是这里的问题。第五数据切片的长度也会影响STFT时频图的幅值。切片越长单张图包含的周期数越多低频分辨率越高但样本数量会减少。我做过一组对比切片长度从512点改到4096点训练集样本数量从几千降到几百模型的泛化能力反而变差。最后权衡下来2048点是一个比较稳的折中值。最后再分享一个实用技巧在训练前把每个样本的时频图做一次直方图均衡化。图像的整体对比度会被拉高故障冲击形成的亮部特征会更加突出CNN的特征提取层能更快地定位到关键区域。这个操作一行代码histeq就能完成但对准确率的提升有时候能达到2%到3%而且几乎不增加训练时间。这套STFT-CNN-BiGRU方法我已经在多个模拟数据集上跑过整体上是稳定可靠的。如果你正打算做故障诊断方向的项目可以先从STFT-CNN搭起把基础流程跑通再逐步引入BiGRU做精度提升。遇到具体问题欢迎按文章里的排查表逐个对照。记住一句话模型只是工具真正决定诊断效果的是你对信号本身理解得有多深。

关于本文作者

来自尧图内容编辑团队

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

尧图内容编辑团队

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

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

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

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

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

网站改版的5个关键决策

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

获取专属建站方案

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

立即免费咨询