news 2026/10/19 5:43:32

同步压缩时频图+多尺度CNN,构建WTMCNN轴承故障诊断

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
同步压缩时频图+多尺度CNN,构建WTMCNN轴承故障诊断

前阵子做旋转机械状态监测项目,用振动加速度信号做轴承故障分类。一开始图省事,直接拿短时傅里叶变换出来的频谱图喂给CNN,测试集准确率卡在90%上下怎么都上不去。后来同事提醒了一句,把输入从普通时频图换成同步压缩时频图,模型结构也从单尺度CNN换成多尺度并行卷积,准确率直接提升了近三个点,而且对变负载工况的泛化明显更好。这个组合就是标题里的WTMCNN诊断网络。

这里想把WTMCNN完整拆开讲清楚。它本质上是把小波多尺度同步压缩变换(WMSST)和多尺度卷积神经网络(MCNN)串联成一套“时频图生成 → 多尺度特征提取 → 故障分类”的端到端流程。文章会给出可参考的MATLAB实现思路、关键参数和踩坑经验,适合正在做故障诊断课题的学生、设备运维工程师,以及想把时频分析+深度学习落地到实际项目里的同行。

1. 思路拆解:为什么是“同步压缩时频图”遇上“多尺度卷积”

1.1 故障诊断的本质还是“读信号”

不管是轴承、齿轮箱还是电机,绝大多数机械故障都会在振动信号上留下痕迹。内圈剥落会产生一系列冲击脉冲,外圈损伤会引起与转频相关的周期性调制,齿轮断齿则会出现啮合频率附近的边带族。这些特征的共同点是:它们既有特定频率成分,又往往随时间动态变化,尤其在启停机、变转速、变负载工况下,信号表现出明显的非平稳特性。

传统做法是直接对整段信号做FFT,看特征频率处有没有明显峰值。但非平稳信号的问题在于,频率成分随时间漂移,一张全局频谱图只能告诉你有这些频率,却看不出它们什么时候出现、如何变化。短时傅里叶变换(STFT)能部分解决这个问题,代价是时间分辨率和频率分辨率互相制约——窗口短了,频率看不清楚;窗口长了,时间定位又变差。这是经典测不准原理在信号分析里的体现,单纯靠调窗口参数很难两全。

小波变换在这个背景下成为主流方案。它用不同尺度的基函数去匹配信号,低频段用长窗口获得高频率分辨率,高频段用短窗口获得高时间分辨率,天然贴合机械振动信号的特性。但连续小波变换(CWT)有个让人头疼的毛病:时频平面的能量是铺散的,明明是一条集中的频率脊线,在时频图上看起来却像一团雾。CNN吃这种模糊输入,学到的特征自然不算最优。

1.2 从CWT到同步压缩,到底改进了什么

同步压缩变换(SST)的核心思想并不复杂:CWT算出来的系数在尺度方向上互相干扰,导致时频能量扩散。那就在尺度方向估计每个点的瞬时频率,再把同一瞬时频率附近的系数全部“压缩”到同一个频率位置上去,相当于把散开的雾重新凝聚成清晰的线。最早提出这个方法的那几位学者,给出的类比就是用“挤压”的方式锐化时频表示。同步压缩不是改变小波变换本身,而是在小波系数平面上做一次非线性重排,物理意义清楚,实现起来也不算难。

多尺度同步压缩变换(MSST)则是在SST基础上进一步迭代。每一轮同步压缩之后,重新从更新过的时频表示里估计瞬时频率,然后再压一次。每多压一轮,能量就更集中一些,时频脊线就更细、更锐利。对含有强噪声、多分量、频率缓慢漂移的振动信号来说,这种迭代锐化的收益非常明显。直观理解就像拍照时连续多次对焦,每次对完再重新测一遍焦点,多来几次画面就清晰很多。

为什么故障诊断特别吃这一套?因为诊断模型的输入质量决定精度上限。CNN再强,也很难从一张涂抹模糊的时频图中区分相近的故障特征。而经过同步压缩的时频图,特征频率、谐波、边带都变成清晰窄带,模型要学的东西简单了,自然更容易收敛、更容易泛化。

1.3 MCNN在特征提取上动了什么脑筋

时频图生成好了,下一步就是分类。常规做法是把时频图直接丢给一个普通的CNN,比如几层3×3卷积堆叠。实际测试中有个现象:小卷积核擅长提取局部纹理,但对时频图中低频段的整体结构和大尺度趋势不够敏感;如果全用大卷积核,高频瞬态冲击这类细节又会被过度平滑。单尺度CNN在时频图分类任务里,本质上是在逼一个固定感受野的网络去做多尺度判别,总会有信息损失。

多尺度卷积神经网络(MCNN)的思路很直接:用多个不同尺寸的卷积核并行处理同一张输入图。一个分支走3×3卷积,负责提取高频冲击细节;一个分支走5×5卷积,捕捉中等尺度的调制结构;另一个分支走7×7甚至更大的卷积核,把握低频整体形态。三个分支各看各的,最后把特征拼在一起。这种做法跟经典Inception结构的思路一脉相承,但用在时频图分类上,针对性更强——因为时频图本身就是典型的多尺度信号结构,低频段和高频段天然需要不同感受野。

把WMSST和MCNN放在一起,等于让信号处理端把时频图画得足够清晰,再让模型端用足够适配的骨架去消化。前者负责“输入质量”,后者负责“特征容量”,两端各做各擅长的部分,组合起来就是WTMCNN这套方案能打的根本原因。

2. WMSST与MCNN的关键细节拆解

2.1 用MATLAB生成WMSST时频图的正确姿势

MATLAB的Wavelet Toolbox从较新版本开始直接内置了多尺度同步压缩变换函数,这是整个流程里最省事的环节。核心调用就一行:

[SST, F] = msst(x, fs);

这里的x是输入振动信号向量,fs是采样频率。返回的SST是频点×时间点的复数矩阵,F是对应的频率轴。默认情况下用的是解析小波,适合大多数机械振动场景,不需要频繁换基。

实际项目中,我通常把信号切成固定长度段再逐个变换。长度选多少很关键:太短,比如只有256个点,时频图频率分辨率不够,故障特征频率和边带根本分不开;太长,比如8192个点,WMSST计算量明显增加,也会把非平稳段内多个工况混在一起。实测下来,1024到4096个点是比较合理的区间,具体看采样频率和设备转速。采样率12000Hz时,我习惯取2048点,差不多0.17秒一段,既能包含足够多的故障冲击周期,计算速度也能接受。

拿到SST矩阵后,还不能直接塞给网络。SST是复矩阵,imageInputLayer只接受实数像素值,通常取模值后再做归一化:

img = abs(SST); img = mat2gray(img); img = imresize(img, [224, 224]);

mat2gray自动把矩阵线性映射到[0,1]区间,这一步不能省。如果不归一化,不同样本之间的幅值差异会引入不必要的方差,模型训练初期特别容易不稳定。

一个小技巧:时频图可以存成单通道灰度图,也可以映射成伪彩色三通道图。模型自己训练(不从预训练网络迁移)时,单通道输入通常就够了,计算量还小一截。但如果你打算用ImageNet预训练权重做迁移学习,就必须映射成三通道。映射伪彩色时,MATLAB里可以这样操作:

rgb = ind2rgb(round(mat2gray(img) * 255) + 1, jet(256));

生成样本时建议先把所有信号段批量变换、批量保存为.mat矩阵,不要一张张存成图片文件。图片小文件IO在样本量上千时会非常慢,而且后续做数据增强不方便。直接保存矩阵,训练时再按需读取和resize,速度能快一个量级。

2.2 多尺度卷积网络怎么搭才能不过拟合

MCNN结构看起来简单,但参数设计直接影响最终效果。我给出一个验证过比较稳的基础结构:

分支一(细节):3×3卷积,32通道,BN+ReLU,2×2最大池化。 分支二(中等):5×5卷积,32通道,BN+ReLU,2×2最大池化。 分支三(全局):7×7卷积,32通道,BN+ReLU,2×2最大池化。

三个分支的输入都是同一张224×224×1时频图。池化后特征图尺寸都是112×112×32,沿通道维度拼接得到112×112×96,再叠加两层3×3卷积进一步融合跨尺度特征,最后接全局平均池化、全连接层、Dropout和softmax分类层。

有几个参数值得特别说明。通道数32是我反复对比后的甜点值——太小了特征容量不够,太大了在样本量只有几百的故障数据集上必过拟合。Dropout放在全连接层前,设0.5,这是故障诊断小样本场景下的标配。BN层加在每个卷积之后、激活之前,能明显加速收敛,也让训练过程对初始学习率不那么敏感。

下面是用Deep Learning Toolbox定义网络的一个参考框架,用layerGraph可以把分支结构搭出来:

lgraph = layerGraph(); tempLayers = [ imageInputLayer([224 224 1], 'Name', 'input') convolution2dLayer(3, 32, 'Padding', 'same', 'Name', 'conv1_1') batchNormalizationLayer('Name', 'bn1_1') reluLayer('Name', 'relu1_1') maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool1_1') ]; lgraph = addLayers(lgraph, tempLayers); tempLayers = [ convolution2dLayer(5, 32, 'Padding', 'same', 'Name', 'conv1_2') batchNormalizationLayer('Name', 'bn1_2') reluLayer('Name', 'relu1_2') maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool1_2') ]; lgraph = addLayers(lgraph, tempLayers); tempLayers = [ convolution2dLayer(7, 32, 'Padding', 'same', 'Name', 'conv1_3') batchNormalizationLayer('Name', 'bn1_3') reluLayer('Name', 'relu1_3') maxPooling2dLayer(2, 'Stride', 2, 'Name', 'pool1_3') ]; lgraph = addLayers(lgraph, tempLayers); tempLayers = [ depthConcatenationLayer(3, 'Name', 'concat') convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv2') batchNormalizationLayer('Name', 'bn2') reluLayer('Name', 'relu2') convolution2dLayer(3, 64, 'Padding', 'same', 'Name', 'conv3') batchNormalizationLayer('Name', 'bn3') reluLayer('Name', 'relu3') globalAveragePooling2dLayer('Name', 'gap') fullyConnectedLayer(64, 'Name', 'fc1') dropoutLayer(0.5, 'Name', 'dropout') fullyConnectedLayer(numClasses, 'Name', 'fc_out') softmaxLayer('Name', 'softmax') classificationLayer('Name', 'output') ]; lgraph = addLayers(lgraph, tempLayers); lgraph = connectLayers(lgraph, 'pool1_1', 'concat/in1'); lgraph = connectLayers(lgraph, 'pool1_2', 'concat/in2'); lgraph = connectLayers(lgraph, 'pool1_3', 'concat/in3');

这个结构不花哨,但胜在稳。如果数据量比较充足(每类500段以上),可以把分支通道数加到64,精度还能再涨一些;数据量有限的话,维持32通道更保险。

2.3 数据划分和增强,决定模型上限的隐形因素

数据集怎么切、样本怎么生成,这步很多人都没认真对待,结果就是训练集和测试集之间存在数据泄漏,准确率虚高得吓人。机械故障数据通常是从一段连续振动记录里截取的,如果直接随机把所有窗口分开,训练集和测试集里很可能包含来自同一段工况、甚至物理上相邻的样本,模型等于带着“记忆”去考试,指标漂亮但一到现场就露馅。

正确做法是按原始连续信号段划分。一种常见工况对应一段独立记录,先把每段记录整体归入训练、验证或测试集合,再从段内滑窗取样本。比如某设备有正常、内圈故障、外圈故障、滚动体故障四类,每类设置了多组不同工况载荷的数据,就按“同工况不同记录”来切分,保证测试集的样本跟训练集完全来自不同时间段。滑窗重叠率可以设50%到75%,用来扩充样本量,但前提是已经按记录段隔离,否则重叠窗口会变成数据泄漏的通道。

数据增强在故障诊断里同样有效。简单有效的三种:给原始振动信号叠加随机高斯噪声(信噪比20dB到30dB),对信号做小幅幅度缩放(0.9到1.1倍),在时频图上做随机左右平移几个像素。前两种在信号域做,后一种在图像域做,实际使用中我倾向于在前端做信号增强,因为物理意义清晰,计算开销也小。增强后的数据集能显著缓解过拟合,尤其对每类只有一百多个样本的冷启动场景。

3. 从零跑通WTMCNN的完整实操

3.1 环境配置和数据集准备

推荐环境是MATLAB R2022a及以上版本,需要安装Wavelet Toolbox、Deep Learning Toolbox,有GPU环境就装Parallel Computing Toolbox。WMSST依赖Wavelet Toolbox内置的msst函数,版本太旧的话可能没有这个函数,要么升级MATLAB,要么自己实现多尺度同步压缩流程,后者成本比较高,不建议折腾。

数据集我以某公开轴承振动数据集为例说明流程:采样频率12000Hz,包含正常、内圈故障、外圈故障、滚动体故障四类,每类多组载荷工况。每组工况取一段连续振动记录,按2.3节的原则划分集合,每段记录内用2048点窗口、50%重叠滑窗取样本。以某类中的某条记录为例,一段十来万点的数据能产出几百个窗口,四类下来每类能拿到几百个样本,总量足够训一个小型MCNN。

数据加载和处理的主循环长这样:

fileList = dir(fullfile(dataRoot, '*.mat')); numFiles = length(fileList); allImages = []; allLabels = []; for i = 1:numFiles data = load(fullfile(dataRoot, fileList(i).name)); x = data.vibration; % 振动信号 label = data.label; % 类别标签 fs = data.fs; % 采样频率 winLen = 2048; step = 1024; nSeg = floor((length(x) - winLen) / step) + 1; for j = 1:nSeg seg = x((j-1)*step + 1 : (j-1)*step + winLen); [SST, ~] = msst(seg, fs); img = imresize(mat2gray(abs(SST)), [224, 224]); allImages = cat(4, allImages, img); allLabels = [allLabels; label]; end end

处理几千个窗口时,这段循环可能要跑一段时间。四个类别每个几百样本,纯CPU环境大概十几二十分钟,能接受;但如果你把窗口数扩到上万,建议改成parfor并行,写几行代码就能把时间压到四分之一左右。

3.2 训练配置和评估指标

网络搭好后,训练参数我用的是adam优化器,初始学习率0.001,MiniBatchSize 32,MaxEpochs 40,ValidationFrequency 10。这些参数不是随手写的:学习率0.001配合BN层是卷积网络的标准配置,太高前期容易震荡,太低收敛太慢;BatchSize 32在GPU显存和梯度稳定性之间比较均衡;Epoch 40配合早停机制(ValidationPatience设5),既给足训练时间,又避免后期过拟合。

训练代码:

options = trainingOptions('adam', ... 'InitialLearnRate', 0.001, ... 'MaxEpochs', 40, ... 'MiniBatchSize', 32, ... 'ValidationData', {valImages, valLabels}, ... 'ValidationFrequency', 10, ... 'ValidationPatience', 5, ... 'Shuffle', 'every-epoch', ... 'Plots', 'training-progress', ... 'Verbose', true); net = trainNetwork(trainImages, trainLabels, lgraph, options);

训练过程中要盯着两条曲线:训练准确率和验证准确率。如果验证准确率某轮开始明显下跌而训练准确率还在涨,就是过拟合信号,早停机制会自动截停。如果两条曲线都平在低点,大概率是时频图生成环节出了问题,别急着调网络结构,先回去看一眼WMSST输出是否正常。

测试评估不能只看一个总准确率。故障诊断领域最常见的坑是类别不均衡和混淆严重,必须看混淆矩阵:

YPred = classify(net, testImages); acc = mean(YPred == testLabels); cm = confusionchart(testLabels, YPred);

重点关注容易混淆的类别对。比如滚动体故障和正常状态偶尔会混,原因是滚动体故障的冲击位置不固定,某些窗口里特征不明显,时频图跟正常状态差别很小。如果这种情况出现较多,可以增加滚动体故障在训练集里的样本权重,或者对滚动体故障样本做更强的数据增强。

3.3 效果对比,如何验证WTMCNN真的有用

验证新方法有没有价值,不能只看最终准确率,得做消融实验,确认每个模块都在起作用。我在项目里做了三组对比:

第一组:输入用普通CWT灰度图,网络用单尺度3×3 CNN。这组是基线,准确率一般在89%到92%之间。 第二组:输入用WMSST灰度图,网络仍用单尺度3×3 CNN。这组单独验证WMSST的贡献,准确率通常能涨到93%到95%,说明输入质量确实提升了分类上限。 第三组:输入用WMSST灰度图,网络用多尺度MCNN。这就是完整WTMCNN,四类故障测试准确率能稳定在96%到98%。

三组对比下来,WMSST和多尺度结构的贡献几乎是各自的。WMSST带来的提升通常比MCNN更大,这是因为时频图质量的改善是从信息源头起作用的,网络再强也补不回丢失的时频细节。这个结论也提醒大家:如果资源有限,优先保证时频图质量,再去升级网络结构,性价比更高。

4. 实操中踩过的坑和排查思路

4.1 时频图生成阶段的几个典型问题

WMSST算出来是复矩阵,很多第一次做的人直接把SST交给imageInputLayer,报错后一脸懵。取模不是可选项,是必须步骤。另外mat2gray归一化前要注意SST矩阵里有没有NaN或Inf,信号段全零或数值异常时可能出现,在循环里加个isnan检查能省很多排错时间。

计算效率是另一个大坑。如果每类数据有上千段、每段生成一张224×224图,普通for循环单核跑起来非常痛苦。我试过一万个样本在普通CPU上跑,差不多要三四个小时。解决思路有三个:一是数据量允许时用2048点窗口缩短单段变换时间;二是用parfor并行;三是先以较小尺寸(比如112×112)保存,训练时再按需resize。实际项目我是三个都用了,处理时间从几小时降到半小时以内。

还有时频图的动态范围问题。振动信号中故障冲击能量往往集中在很窄的频率带,abs(SST)矩阵的数值可能从0到几千甚至上万,直接用mat2gray会把微弱的高频细节压到接近零,导致网络完全学不到这些信息。遇到这种情况,先对abs(SST)做对数变换再归一化——log(1 + abs(SST))能把动态范围压缩不少,高频细节的可视性明显改善。这个操作在故障特征较弱的早期损伤场景下尤其重要。

4.2 模型训练阶段的过拟合和不均衡

样本量不足是故障诊断项目常态。若MCNN分支通道数偏大或全连接节点过多,训练两三轮后训练准确率就到98%,验证准确率却停在90%,典型过拟合。处理手段优先级从高到低:先砍全连接宽度,把fc1节点从128降到64;再把分支通道数从64降到32;最后加Dropout到0.6。这三步做完,验证准确率通常能拉回几个点。

类别不均衡也很常见,比如正常运行时间极长导致正常样本数量远超故障样本。直接用原始分布训练,模型会偏向多数类。处理办法是让每个mini-batch里各类样本数量尽量均衡,用MATLAB的classWeights给少数类更大的损失权重,或者在每个epoch内对少数类过采样。我用过第二种,效果直接,实现也简单。

训练曲线上还有一种情况:验证准确率来回抖,每10轮验证波动超过两三个点。这通常是验证集太小或者数据划分没做好随机性,检查一下是否不同类别的验证样本分布不均,再回头核对2.3节的划分逻辑。划分逻辑没问题,就适当增大验证集比例到20%。

4.3 部署和扩展时的高频命中率建议

模型在测试集上拿到98%的准确率,别高兴太早。拿到现场数据上跑一遍,往往发现实际准确率掉到85%都不到。原因不在模型,在于训练数据和应用数据之间的分布差异——现场环境有背景振动、安装共振、噪声干扰,这些在公开数据集里都不存在。应对办法是在训练阶段就主动做噪声增强,把SNR 20dB噪声样本混进去;如果现场有已知干扰频率,还可在数据预处理阶段加窄带滤波。

WTMCNN这套流程不局限在轴承上。齿轮箱的啮合频率调制、电机转子断条、泵的叶轮通过频率,在我看来都可以用这个框架做。只要故障能用振动信号表达、能在时频图上形成可辨识模式,就值得试一次。换设备之后要重新调整的是窗口长度、频率轴范围和时频图输入尺寸,网络骨架基本不用动。后续想进一步工程化,可以把MCNN换成更轻量的MobileNet结构,或者把分类头换成Transformer,这些都是顺着WMSST+MCNN思路的自然延伸。

最后分享一点个人体会。WMSST计算量不小,很多人图省事直接用FFT频谱图或普通CWT图,结果模型怎么调都到不了理想精度。如果做离线诊断,果断上WMSST,时频图质量带来的收益远大于多花的计算时间;如果做实时在线监测,先用CWT把流程跑通,再把WMSST单独加速后可部署。这套组合的扩展空间确实很大,后面完全可以沿着轻量化、在线化继续往深处走。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/19 5:43:28

美团App逆向爬虫实战:Frida+APK分析+协议解密全流程

简介:这是一份面向Python中级开发者与数据采集实践者的美团App端数据爬取实战项目,聚焦反爬应对、接口逆向与结构化存储等核心难点,适用于安全研究、竞品分析及本地化数据集构建等场景。压缩包共23个文件,含7个Python主控与逻辑脚…

作者头像 李华
网站建设 2026/10/19 5:43:05

LITESTAR 4D道路照明设计:从参数建模到计算报告的全流程解析

做道路照明设计这些年,我越来越觉得,真正拉开项目差距的往往不是“会不会画图”,而是“能不能把光算明白”。LITESTAR 4D的道路附加模块,就是我在无数个改图夜晚里慢慢用顺手的工具。它解决的并不是“把路照亮”这种笼统的问题&am…

作者头像 李华
网站建设 2026/10/19 5:42:29

Python代码执行过程全解析:从源码到字节码再到虚拟机

写 Python 有年头的人,面对再复杂的框架都能上手,可一旦被问到“Python 代码执行过程”到底是怎么跑的,多少会卡壳。以前我在某项目里排查一个诡异的内存增长问题,程序里没写循环也没开线程,但 RSS 就是一路往上涨。最…

作者头像 李华
网站建设 2026/10/19 5:41:12

virtio-gpu 架构详解:从虚拟显卡原理到云桌面与 GPU 虚拟化实践

前端时间在给一套虚拟化场景调显示渲染链路,又把 virtio-gpu 的客户机驱动、QEMU 设备模型和宿主机渲染后端整个翻了一遍。坦白讲,很多人对 virtio-gpu 的印象就是 QEMU 命令行里的一行-device virtio-gpu,以为它只是一块“能显示画面的虚拟显…

作者头像 李华
网站建设 2026/10/19 5:40:52

一句话生成数据大屏:PY880窗体设计器实测与架构解析

1. 一句话做数据大屏,这个想法到底靠不靠谱第一次听到“一句话做数据大屏”这个说法,我脑子里蹦出来的第一个念头是:又来了,又是一个营销噱头。毕竟在这个圈子里混了十来年,见过太多号称“零代码”“一键生成”“人人都…

作者头像 李华
网站建设 2026/10/19 5:40:52

Swift源码安全审计:静态分析如何让漏洞无处可藏

项目标题: "告别代码安全焦虑!Swift Code源代码安全审计工具,让漏洞无处可藏" 项目正文: 针对Swift开发者的源代码安全审计工具,帮助发现潜在安全漏洞和代码缺陷。 关键词: Swift, 代码审计, 安全漏洞, 静态分析 摘要描述: 分享一款…

作者头像 李华