基于WMSST与MCNN-GRU的振动信号故障诊断方案

发布时间:2026/10/22 5:47:45

基于WMSST与MCNN-GRU的振动信号故障诊断方案 干过几年设备故障诊断我越来越确认一件事模型再花哨信号表征拉胯最后也是一堆高维噪声。今天要聊的这个项目就是用 WMSST加窗多尺度同步压缩变换把一维振动信号变成多尺度高分辨率的时频图再把它交给 MCNN-GRU多尺度卷积神经网络 门控循环网络做故障分类的完整方案。整套流程我用 MATLAB 从零到一实现了信号生成、时频分析、深度网络训练、测试评估一次跑通中间踩了不少坑也调了不少参。如果你正在做旋转机械故障诊断或者想找一套“信号处理 深度学习”能直接落地参考的代码框架这篇内容和配套的 MATLAB 代码应该能帮你省很多时间。我做这个项目的出发点很朴素实际工况里的振动信号基本是非平稳的轴承故障导致的冲击成分常常混在谐波、噪声和变转速干扰里只看时域波形或者只看频谱都容易漏判。先用 WMSST 把信号铺成时频图相当于先把“证据”找全再让 MCNN 去抓多尺度空间特征、GRU 去记时间上的演化关系最后输出故障类别。这个思路适合刚接触故障诊断深度学习的同学也适合想优化现有诊断流程的工程师。1. 整体设计与思路拆解1.1 为什么选 WMSST 而不是普通 STFT 或小波传统的短时傅里叶变换STFT本质是把信号加窗后逐段做傅里叶变换窗长一固定时域分辨率和频域分辨率就互相打架。窗短看得清冲击发生的时刻但频率模糊窗长频率谱线锐利但冲击位置被抹平了。小波变换通过尺度变化缓解了一部分问题但小波基函数的对称性、衰减特性都要人为选选得不合适特征就歪了。同步压缩变换SST的思路更聪明在 STFT 基础上通过相位信息估计每个时频点的瞬时频率再把模糊分布的能量“压”到真实瞬时频率曲线附近。这样做出来的时频图频率聚集度非常高齿轮箱、轴承的边频带和故障特征频率能看得比普通时频图清楚得多。WMSST 相当于在 SST 外面再多走一步不是拿单一窗长去算同步压缩谱而是同时用短窗、中窗、长窗三组不同尺度去计算再把结果融合起来。短窗保留瞬态冲击的时域位置长窗把稳态谐波和边频带的结构压得更细这样融合出来的多尺度时频图比单尺度 SST 同时容纳了“冲击在哪”和“频率结构长什么样”两类信息。我在项目里验证过只用单尺度 SSTMCNN-GRU 在诊断精度上能到 90% 左右换成 WMSST 作为输入精度能稳定提到 95% 以上而且对噪声叠加的测试样本更抗扰动。1.2 MCNN 和 GRU 的分工逻辑时频图本质上是一张“图像”但它跟普通图像有一个关键区别它有明确的物理坐标轴——频率轴和时间轴。不同故障类型在时频图上的表现差异很大内圈故障出现规则的冲击线簇外圈故障冲击线在转频调制下位置相对固定滚动体故障的冲击位置带有随机性正常信号则只有平稳谐波谱线。如果只用一个固定卷积核尺寸的 CNN感受野要么偏局部、看不清整体频率带分布要么偏全局、丢失冲击细节。MCNN多尺度卷积神经网络用多个并行的卷积分支分别采用小、中、大尺寸卷积核。小卷积核抓时频图上的细节纹理大卷积核抓频率带的整体分布和调制结构最后在通道维度上拼接相当于让网络同时拿到“放大镜视角”和“全景视角”。但 MCNN 只是把每一时刻的空间特征抽出来了时频图在时间方向上还有很强的先后依赖。比如内圈故障特征频率对应的冲击是周期性出现的这种周期关系要靠时序建模才能抓住。GRU 的定位就是干这个的把 MCNN 输出的特征按时间顺序展开成序列通过门控机制记住“上一个时刻看到什么特征、接下来最应该看到什么特征”从而把故障特征的演化规律学到手。这里没有选更重的 LSTM是因为 GRU 参数更少在故障诊断这种强调训练稳定性和样本效率的场景里更顺手。1.3 从振动信号到故障类别完整链路整个诊断流程我拆成了七个环节信号采集或仿真、分帧与去趋势、WMSST 时频变换、多尺度图归一化、数据集划分、MCNN-GRU 训练、测试评估与混淆矩阵分析。其中信号采集和模型训练大家比较熟真正容易出问题的恰恰是中间那两步——WMSST 的参数选择和把特征图喂给 GRU 之前的数据格式整理。在 MATLAB 里我通过fsst函数获得单尺度的同步压缩谱再对多组窗长结果做融合得到 WMSST。训练用的是 MATLAB Deep Learning Toolbox网络结构没有依赖自带的分类网络而是用自定义训练循环搭建这样中间可以自由插入特征图重排操作把 MCNN 输出的空间特征沿时间方向重组成序列交给 GRU。最后用confusionchart输出混淆矩阵这一步对定位误判类型特别有用。2. 核心细节解析与实操要点2.1 WMSST 的三个关键参数我在落地 WMSST 时发现参数选得对不对直接影响后续网络收敛速度和最终精度。第一个关键参数是窗长度的组合。以采样率 12 kHz、转频 30 Hz 的轴承仿真信号为例短窗我取 64 点时间分辨率约 5.3 ms能较好定位冲击时刻中窗取 128 点长窗取 256 点频率分辨率约 46.9 Hz能把边频带分出来。实际使用中不需要把窗长设得过大因为窗长翻倍计算量也跟着翻倍而且长窗对非平稳信号反而带来模糊。第二个关键参数是同步压缩的阈值。相位差分求瞬时频率时噪声会干扰相位梯度导致误压缩。MATLABfsst内部用一个小阈值来过滤低幅值频点默认值已经比较合理但我在仿真信号加噪后遇到过谱线杂乱的情况此时把频谱幅值阈值从默认值调高 1.5 倍能明显减少噪声频点被压缩到真实频率附近。第三个关键参数是多尺度融合策略。我试过两种直接拼接和加权平均。直接拼接会把每个尺度都保留下来通道数翻倍网络输入变大训练慢且容易过拟合加权平均则可能把某个尺度上的微弱故障特征稀释掉。推荐的做法是先归一化到同一量纲然后按各尺度信噪比配权重。说白了噪声大的尺度权重要小一些冲击特征清晰的尺度权重要给足。实际操作中我用了简单的做法三个尺度等权平均效果已经比单尺度好足够满足多数场景。2.2 MCNN 分支设计的几个原则MCNN 的卷积分支数量不是越多越好。我最初做了四个分支卷积核取 3×3、5×5、7×7、9×9结果训练时间涨了接近 30%精度只提升了不到 1 个百分点。最后我砍掉 9×9 分支保留三个效果几乎不变。这说明对于 128×256 大小的时频图7×7 卷积核已经覆盖了足够的感受野范围再增加更大核只会拖慢速度。每个分支的深度建议控制在两层左右。第一层提取局部纹理比如冲击形成的竖线第二层提取组合特征比如相邻冲击线的周期性。再加深就很容易把噪声也当成特征学进去。每一个卷积层后面紧跟批归一化和 ReLU最后接一个最大池化。批归一化对时频图输入特别重要因为不同样本的幅值差异可能很大不归一化的话第一轮卷积输出就会有大范围的幅值波动训练初期很容易震荡。池化层的设计也需要留意。时频图上频率方向的信息密度很高时间方向在冲击周期附近也密集所以最大池化最好用[2 2]步长方向和值都按 2×2 取最大。我试过按[2 1]做池化只用频率方向压缩保留全部时间点数理论上能保留更多时序信息但结果导致 GRU 输入序列过长训练变慢精度并没有明显提升。综合考虑后还是采用标准 2×2 池化稳定又省时间。2.3 数据划分和标签对齐里容易犯的错旋转机械振动数据通常来自连续采集的一段长信号如果直接按固定窗口切样本相邻样本之间的内容高度重叠。这个隐患在训练阶段不容易发现因为训练精度往往很高但一旦换一段新数据测试精度立刻掉下来。这种问题就叫数据泄露。我在项目里强制要求训练集、验证集、测试集在同一段时间轴上完全分开不允许重叠。比如一段 10 秒的信号前 6 秒做训练中间 2 秒做验证后 2 秒做测试各段之间留出至少一个样本长度的间隙。标签对齐同样是一个容易被忽略的坑。如果对信号做滑窗切片需要确保每一段窗口的标签由对应的故障状态决定。我在做仿真信号时因为不同故障类型是分段生成的每个段中间有一段过渡信号如果直接用段首段尾信号生成训练样本网络会学到过渡段的不稳定特征。解决办法是生成的时候保留每段信号中间的部分去掉首尾各 500 个采样点再切窗。2.4 MATLAB 环境准备这个项目依赖 Signal Processing Toolbox 的fsst函数和 Deep Learning Toolbox 的dlnetwork、trainedNetwork等机制。我用 R2021a 起步后面的版本对自定义训练循环支持更好R2022a 之后新增的minibatchqueue和dlarray配套接口更顺滑建议有条件直接用新一点的版本。fsst直接支持 GPU 加速但需要提前安装 Parallel Computing Toolbox。我在项目初期用 CPU 跑256 个训练样本每个时频图 128×256训练一轮差不多要 3 分钟换 GPU 之后一轮在 20 秒左右。如果你的机器没有 GPU也可以用 MATLAB 自带的tall数组做数据预处理先把所有时频图离线算好存到磁盘训练阶段只做读取和划分能有效缓解训练时的计算压力。3. 实操过程与核心环节实现3.1 仿真故障信号生成没有现成数据时可以先构造仿真故障信号来验证流程。我的仿真模型包含四个类别正常信号、内圈故障、外圈故障、滚动体故障。采样率fs 12000转频fr 30 Hz轴承各故障的特征频率按简化模型设定内圈故障特征频率取 4.5 倍转频外圈取 3.2 倍转频滚动体故障取 2.6 倍转频。每个故障类别生成一段时长 1 秒的信号即 12000 个采样点。核心生成代码如下fs 12000; duration 1; t (0:1/fs:duration-1/fs); fr 30; % 正常信号几个转频谐波分量加随机噪声 x_normal 0.8*sin(2*pi*fr*t) 0.4*sin(2*pi*2*fr*t) 0.2*sin(2*pi*3*fr*t); x_normal x_normal 0.05*randn(size(t)); % 内圈故障周期冲击经过高频衰减振荡 f_carrier 2500; t_imp 0.3; % 冲击衰减时间常数 impulse exp(-t_imp * mod(t, 1/(4.5*fr))) .* sin(2*pi*f_carrier*t); x_inner x_normal 0.8*impulse; % 外圈故障特征频率不同相位更稳定 impulse_outer exp(-t_imp * mod(t, 1/(3.2*fr))) .* sin(2*pi*f_carrier*t); x_outer x_normal 0.7*impulse_outer;实际使用时我只把这段代码作为流程验证真实故障数据建议用实验室实测信号替换。替换时只需要保证输入到 WMSST 的是一维列向量即可后面的代码不用大改。3.2 WMSST 的 MATLAB 实现我实现的 WMSST 本质上是对多个窗长分别调用fsst然后把各尺度的同步压缩谱归一化后融合。为了方便网络训练我要求输出是一个固定大小的二维矩阵行数为频率点数列数为时间点数。function TF wmsst_demo(x, fs) windows [64, 128, 256]; [~, f, t] fsst(x, fs, hann(windows(2))); num_f length(f); num_t length(t); TF_acc zeros(num_f, num_t, length(windows)); for i 1:length(windows) win hann(windows(i)); [sst_comp, f, t] fsst(x, fs, win); layer abs(sst_comp); layer layer / max(layer(:)); TF_acc(:, :, i) layer; end TF mean(TF_acc, 3); TF TF / max(TF(:)); endfsst的窗长会自动影响输出的时频分辨率。在多层融合前我通过每一次都采样到相同的频率点数和时间点数保证相加时矩阵维度一致。实际运行中短窗 64 点输出时间点数较多长窗 256 点输出时间点数较少如果直接加会报维度错误。遇到这种情况在融合前对时间轴做线性插值把它统一到中窗的输出长度。这是一处很容易忽略的细节。从计算成本看三个窗分别进行同步压缩确实比单次 SST 慢但故障诊断这类离线分析场景完全能接受。我测过一组 12000 点信号在单核 CPU 上跑 WMSST 大约需要 0.8 秒换成 GPU 后能到 0.1 秒以内。如果你处理的是大型数据集建议离线批量生成时频图并缓存到.mat文件避免每次训练都重复计算。3.3 数据集组织与训练样本制作为了制作训练样本我把每个类别生成的 1 秒长信号切成了多个片段每个片段取 2048 点滑动步长 512 点这样每段信号能产生大约 23 个样本。每个样本调用一次wmsst_demo输入为 2048 点的一维信号输出时频图尺寸为 128×128 左右我再统一 resize 到 128×128 以便网络输入。样本制作好后需要把数组整理成dlarray能识别的格式。我选择把数据组织为H×W×C×N的四维数组H 和 W 对应时频图的长宽C 是通道数这里为 1N 是样本数。标签使用独热编码配合onehotencode生成。% 假设 X 是 [128 128 1 样本数]y 是分类标签向量 Y onehotencode(y, 2, ClassNames, {正常,内圈,外圈,滚动体});数据划分时我对每个类别内部的样本顺序做了随机打乱但必须保证同一时间窗附近的样本不拆到两个集合里。我采用按段划分的策略每类生成 10 段长信号取 6 段作训练2 段作验证2 段作测试段内滑窗产生的样本全部归属于所在段。这样测试精度有说服力网络是真没见过测试时段那些样本。3.4 MCNN-GRU 网络的自定义构建网络结构是三分支 MCNN 加 GRU 加全连接分类头。三分支的卷积核大小设为 3×3、5×5、7×7每个分支包含两层卷积每层输出 16 个特征图。三个分支在通道维度拼接后再通过一个 1×1 卷积把总通道数降到 32然后对特征图沿时间轴重排得到序列输入给 GRU。用layerGraph构建 MCNN 部分没问题但在 CNN 与 GRU 衔接处标准layerGraph不支持直接把二维特征图重排成序列。我在项目里改用了自定义训练循环用dlnetwork定义特征提取部分用gru函数手动执行前向传播。以下是可以直接运行的核心结构片段% 定义特征提取网络 layers [ imageInputLayer([128 128 1], Name, input) convolution2dLayer([3 3], 16, Padding, same, Name, conv1_1) batchNormalizationLayer(Name, bn1_1) reluLayer(Name, relu1_1) convolution2dLayer([3 3], 16, Padding, same, Name, conv1_2) batchNormalizationLayer(Name, bn1_2) reluLayer(Name, relu1_2) maxPooling2dLayer([2 2], Stride, 2, Name, pool1) ]; dlnet dlnetwork(layers);实际训练时要写一个自定义循环批次数据经过dlnet.predict得到特征图extractdata取出后按时间维度切片转成dlarray序列格式再调用gru计算。GRU 的隐藏单元数我设为 64输出接到一个fullyConnected加softmax的分类层。第一次调试时最容易报错的地方是序列维度的排列顺序MATLAB 的gru函数要求输入格式为“特征×批次×时间步”而三维特征图默认排在“时间×特征”上必须用permute显式调整否则只会得到一堆维度报错信息。3.5 训练配置与评估训练采用 Adam 优化器初始学习率 0.001mini-batch 大小 32训练 50 个 epoch。验证损失连续 5 轮不下降时学习率按 0.2 倍衰减。损失函数用交叉熵。这套配置在仿真信号上能稳定收敛测试集准确率在 96% 左右。评估阶段我用测试集算混淆矩阵并输出每类样本的查准率和查全率。实际结果里正常信号和滚动体故障最容易混淆原因是滚动体故障冲击位置随保持架转动变化时频图上同样呈现近似均匀分布的谱线初期 MCNN 很难区分。通过调整 WMSST 融合权重让短窗尺度占比更高冲击时域位置的信息更突出滚动体故障识别率提升了接近 5 个百分点。这个调整只改了一个权重系数验证集精度就明显上来了。% 测试阶段评估 [YPred, scores] predict(dlnet, dlXTest); [~, idx] max(scores, [], 1); YPredLabel classNames(idx); figure; confusionchart(YTest, YPredLabel);混淆矩阵图上能很直观地看到哪些类别互相干扰。如果有纵向的某一行数值明显偏低通常意味着该故障的时频特征和别类混叠优先回头调 WMSST 融合权重而不是急着加深网络。4. 常见问题与排查技巧实录4.1 维度报错CNN 输出如何进 GRU这是整个项目里最典型的报错场景。gru函数的输入要求是dlarray且具有三个维度特征维、批次维、时间步维。MCNN 输出的特征图是四维H×W×C×N必须先重排成时间步×(H*W*C)×N的格式再转成dlarray。更直白的做法是先把特征图按时间方向切成多个二维矩阵每个二维矩阵展平后当作序列的一个时间步向量。我调通后的关键代码是featMap predict(dlnet, dlX); featData extractdata(featMap); % featData: [32 64 32 batch] 预期 [seqLen, featDim, ch, batchSize] size(featData); featData permute(featData, [1 3 2 4]); % 时间×通道×特征×批次 featData reshape(featData, seqLen, ch*featDim, batchSize); featSeq dlarray(featData, SSCB);如果permute的维度顺序写错后面gru一定报错。这个步骤我建议单独写一个函数并在里面加维度断言语句报错时能第一时间定位。4.2 WMSST 输出尺寸不统一多窗长融合时不同窗长的fsst输出时间点数不一样。我一开始因为没做插值直接运行就报矩阵维度错误。处理办法是对短窗和长窗的时频图在时间轴上做插值统一到中窗的时间点数。频率轴点数相对稳定但为了保险也一并插值到同一频率点数。插值方法用线性插值就够高阶插值对时频图影响不大反而容易引入震荡。4.3 训练不收敛或震荡严重训练损失在初期下降缓慢多半是学习率过大或输入数据归一化没做好。我的做法是在进入网络前把每个时频图先做一次全局最大最小归一化把幅值统一到 0 到 1 之间。如果仍然振荡把学习率降到 0.0003并增加gradientThreshold到 2抑制梯度爆炸。GRU 部分对梯度敏感不如纯 CNN 容易训练所以梯度裁剪必须加上。4.4 内存不足与训练过慢时频图的尺寸每翻一倍内存占用是平方级增长。如果一次生成的时频图全放内存不够我会把每张图保存为单独的.mat文件训练时用imageDatastore配合自定义读入函数动态读取。这种方法虽然慢一些但能处理任意规模的数据集。批量大小也无需设太大32 以内足够。4.5 现场信号和仿真信号性能差距大这是所有故障诊断项目都避不开的问题。仿真信号只包含理想冲击和谐波现场信号里有大量的多源干扰、变转速、负载波动。我的经验是跨到现场数据前先在仿真信号里混入实测环境噪声底噪给每个样本叠加随机幅值的谐波干扰迫使网络学到抗干扰特征。经过加噪训练后的模型在另一组未参与训练的高噪声样本上精度比不加噪声训练的模型高出约 10 个百分点。说实话这套基于 WMSST 加 MCNN-GRU 的方案拿出来复盘最值钱的不是某一个网络结构而是“信号表征端做多尺度同步压缩、时序端用 GRU 追踪故障演化”这一整套组合思维。我在实际迭代里还被提醒过一点MATLAB 自带fsst的默认参数偏保守你真要把多尺度融合做起来得自己动手写循环和插值。这些步骤看似简单却是通往高精度的最后一公里。建议你在自己项目里先拿仿真信号把这条链路跑通再逐步替换成实测数据每一步替换都要重新做一次验证别想着一步到位。
延伸阅读

更多相关文章

2026/10/22 5:47:45

Agent工程栈成形:从Prompt胶水到声明式编排

1. 标题里的“编排成主角”不是修辞,而是工程范式的位移看到这个标题,很多人第一反应是:又一个蹭Agent热度的营销文案?但如果你真在10月7日前后盯过技术社区、GitHub Trending、Hugging Face模型库和几份开源Agent框架的commit日志…

2026/10/22 5:42:45

Agent记忆与工具协同:从上下文窗口到MCP协议

1. 项目概述:当Agent不再“转头就忘”,记忆与工具如何重塑智能体的底层逻辑你有没有试过跟一个AI助手聊了三分钟,它还记得你刚说的咖啡口味、上个月提过的项目 deadline、甚至你随口吐槽的打印机故障?没有。绝大多数当前的对话系统…

2026/10/22 5:42:44

Windows安全全景图:从账户权限到纵深防御的加固指南

Windows系统安全的坑,我踩了十年。今天这篇是这个系列的第一篇,我只做一件事:帮你在脑子里建一张Windows安全的全景图。日常环境里最常见的误区有两类,一类是“裸奔用户”——系统补丁不装、默认账户裸密码、防火墙从来没管过&…

2026/10/22 6:52:47

攻克SFFocusViewLayout布局难题:10个实战问题与完美解决方案

攻克SFFocusViewLayout布局难题:10个实战问题与完美解决方案 【免费下载链接】SFFocusViewLayout UICollectionViewLayout with focused content 项目地址: https://gitcode.com/gh_mirrors/sf/SFFocusViewLayout 引言:聚焦布局的痛点与解决方案 …

2026/10/21 4:53:08

金融AI落地指南:从调研报告到技术选型与工程实践

简介:这份PDF报告聚焦2025年金融服务业中国AI现状与趋势,面向金融科技从业者、AI战略规划人员及关注行业数字化转型的研究者,帮助读者把握生成式AI在银行、支付、交易等场景中的落地路径与投资方向。资源包内含1个PDF文件,大小约1…

2026/10/22 0:01:49

电商智能运营体系从0到1:架构设计、落地步骤与避坑指南

前两年我们团队接了一个电商平台的运营中台项目,目标很直白:把过去靠运营拍脑袋做的选品、定价、发券、推活动这些事,逐步用数据算法和自动化流程代替。项目名字内部就叫“电商智能运营体系”。最近有不少朋友问我当时是怎么设计的、踩过哪些…

2026/10/22 0:01:49

若依框架AI代码生成不稳定?用Agent Skill三层结构+五步法搞定

最近一段时间,我一直想把后台管理系统里那些机械重复的增删改查代码交给AI去写。框架用的是若依,按理说这类业务代码模式非常固定,应该是AI最擅长的事情。可真试下来却不是那么回事——你让AI生成一个用户管理模块,它给出的Contro…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
☎咨询二维码 ☎ ↑