☰
基于DWVD与MCNN的旋转机械故障诊断方法与实践
2026/10/22 22:05:56 网站建设 项目流程

1. 故障诊断这条路,为什么我最后选了 DWVD + MCNN

搞旋转机械故障诊断这几年,我试过不少方案。早期做频谱分析,拿 FFT 看幅值谱,简单是简单,但遇到变转速、冲击性强、信噪比低的工况,频谱图上一片糊,特征频率根本找不准。后来转向时频分析,小波变换、经验模态分解都折腾过一阵,各有各的毛病——小波基函数选起来看缘分,EMD 模态混叠折腾得人头疼。直到把离散韦格纳分布(DWVD)和多尺度卷积神经网络(MCNN)搭到一起,才算是找到一条效果稳定、流程清晰、代码也好复现的技术路线。

这套 DVMCNN 方案解决的核心问题,说白了就是两件事:一是怎么把一维振动信号里藏着的故障特征干净地“捞”出来,二是怎么让网络不用靠人工调特征就能自动把不同故障分得明明白白。DWVD 负责前者,它的时频聚集性比短时傅里叶变换强不少,能把信号的能量在时频平面上怼成一条细线,故障特征一眼可见;MCNN 负责后者,用多尺度卷积核并行提取不同粗细的特征,比单一尺寸卷积核更能适配复杂振动信号里“大趋势里有小毛刺”这种特点。

这篇文章适合谁看?正在做故障诊断课题的学生、刚接触时频分析加深度学习的工程师,以及想在 MATLAB 里完整跑通“信号处理 + 网络训练 + 识别评估”这条链路的人。我会把 DWVD 的原理、交叉项抑制办法、MCNN 结构设计逻辑、完整 MATLAB 实现流程和调试中踩过的坑一次说清楚。代码部分我会挑核心段落贴出来解释,完整的工程文件可以按文中思路自行搭建,几分钟就能跑起来。

2. 为什么是 DWVD:时频分析方案选型的逻辑

2.1 从 STFT 到 WVD,差的不是一点半点

先说一个基本问题:滚动轴承或齿轮箱的故障信号,本质上是非平稳信号。故障引起的冲击会调制出周期性脉冲,这些脉冲在频谱上表现为以某个共振峰为中心、以故障特征频率为间隔的边带族。如果只用传统频谱分析,这些边带容易被噪声淹没,而且变转速工况下频谱是“糊”的,特征会平移、变形,没法直接对比。

时频分析的意义就在于把时间、频率两个维度同时展开。短时傅里叶变换(STFT)是加窗的 FFT,窗长定了,时间分辨率和频率分辨率就互相掐架——窗短了频率看不清,窗长了时间定位不准。小波变换虽然能自适应分辨率,但小波基的选择没有统一标准,换了数据就得重新试。

Wigner-Ville 分布走的是另一条路。它不切窗,而是把信号和信号的延迟副本做相关运算,再对延迟做傅里叶变换。数学形式是:

[ WVD(t,f) = \int x(t+\tau/2) x^*(t-\tau/2) e^{-j2\pi f\tau} d\tau ]

这个分布的理论时频聚集性极佳,对单分量线性调频信号,它能给出理想的“能量脊线”,这是 STFT 和小波变换都做不到的。理论上讲,它的时频分辨率不受不确定性原理约束,这也是它被称为“高分辨率时频表示”的原因。

2.2 DWVD 的实际计算过程

离散化之后,输入信号为 x[n],长度 N,离散韦格纳分布在 MATLAB 里的核心计算可以写成:

function [tfr, f] = myDWVD(x, fs) N = length(x); if mod(N, 2) ~= 0 x = x(1:end-1); N = length(x); end tfr = zeros(N, N); t = (0:N-1) / fs; f = (0:N/2-1) * fs / N; for n = 1:N tau_max = min([n-1, N-n, round(N/2)-1]); tau = -tau_max:tau_max; x_shift1 = zeros(1, length(tau)); x_shift2 = zeros(1, length(tau)); for k = 1:length(tau) if (n + tau(k)) >= 1 && (n + tau(k)) <= N x_shift1(k) = x(n + tau(k)); end if (n - tau(k)) >= 1 && (n - tau(k)) <= N x_shift2(k) = x(n - tau(k)); end end R = x_shift1 .* conj(x_shift2); tfr(n, :) = abs(fft(R, N)) .^ 2; end tfr = tfr(:, 1:N/2)'; end

别急着复制去跑,这个版本是裸的 WVD,双分量信号跑出来交叉项能盖过真实特征。我当初第一次跑出这种图的时候,满屏幕都是震荡条纹,真实故障频率完全看不清,整个人是崩溃的。

2.3 交叉项问题与核函数抑制

交叉项是 WVD 的固有缺陷。当信号包含两个分量时,WVD 会在两个分量之间的时频位置产生振荡的伪能量,幅度甚至能超过真实分量。生活化类比就是:双人合唱时,录音里除了两个人的歌声,还有一个“第三个人”的混响声音,而这个混响不是任何人唱出来的。

抑制交叉项的标准做法是在模糊域乘核函数,也就是把 WVD 变成 Cohen 类分布的一种。我实际用的是平滑伪 WVD(SPWVD),通过时域窗和频域窗同时平滑来压制交叉项。MATLAB 里有现成函数可以做时频分析,不过我习惯自己控制核函数的参数,因为默认参数不一定适合自己的信号。

关键参数就这么几个:

参数作用我的取值调整经验
时域平滑窗长度控制时间维度的平滑程度5~11越长交叉项越弱,但时间分辨率下降
频域平滑窗长度控制频率维度的平滑程度5~9过长会把真实窄带特征抹掉
信号长度 N时频图尺寸512 或 1024建议 2 的幂次,后续送 CNN 也方便

我的经验是:先拿一段已知故障类型的数据跑一遍,把交叉项压下去但不明显损失主频带的锐度,然后固定参数,整个数据集统一用这套参数,免得每个样本单独调参导致特征分布不一致。

DWVD 的输出是一张二维时频图,横轴是时间,纵轴是频率,像素亮度代表能量强度。这张图就是后面 MCNN 的输入。所以时频变换这一步做得好不好,直接决定网络的天花板——输入已经糊了,网络再强也白搭。

3. MCNN 多尺度卷积网络的结构设计逻辑

3.1 为什么单尺度 CNN 不够用

故障振动信号的时频图有个特点:不同故障类型对应的特征尺度差异很大。比如滚动体故障的冲击特征比较窄、局部性强,在时频图上表现为细碎的亮点簇;而保持架故障的特征往往更宽,表现为大范围的能量团块。如果只用单一尺寸的卷积核,要么捕捉局部细节但丢了全局上下文,要么看到全局轮廓但漏了细小的冲击特征。

标准 CNN 靠堆层数来扩大感受野,但层数越深参数越多,训练数据不够就容易过拟合。而且深层网络的梯度传播路径长,小数据集下训练不稳定。多尺度卷积网络解决这个问题的思路更直接:在同一层里并行使用不同尺寸的卷积核,各看各的尺度,最后把特征拼起来。

3.2 网络结构具体设计

我用的 MCNN 结构是这样的:

层类型具体配置输出尺寸
输入层64×64×1(归一化后的时频图)64×64×1
多尺度卷积块11×1 卷积(32通道),3×3 卷积(32通道),5×5 卷积(32通道),并行64×64×96
BatchNorm + ReLU逐通道归一化 + 激活64×64×96
最大池化2×2,步长232×32×96
多尺度卷积块21×1 卷积(64通道),3×3 卷积(64通道),5×5 卷积(64通道),并行32×32×192
BatchNorm + ReLU同上32×32×192
全局平均池化每通道取平均1×1×192
全连接层192 → 6464
Dropout概率0.564
输出层Softmax,类别数 = 故障类型数类别数个

这里每个多尺度卷积块里的三个卷积核是并行关系,输出在通道维度上直接 concatenate。1×1 卷积负责逐像素的特征变换和降维,3×3 是标准感受野,5×5 提供更大的上下文范围。三个尺度互补,比单独用 3×3 堆叠的效果明显好。

3.3 参数选择的理由和教训

通道数这块,我一开始为了追求效果把第一层通道设成 64/64/64,结果训练集只有几千张图,网络直接过拟合,训练准确率 100%,验证集只有 80%。后来把通道数降到 32/32/32,配合 Dropout 和数据增强,验证集反而上去了。这个教训说明:小数据集上,网络容量不是越大越好,够用就行。

输入尺寸我选定 64×64,而不是直接把原始时频图全尺寸塞进去。原因有二:一是 DWVD 输出矩阵是 N×N/2,N 取 512 时就是 512×256,直接送网络参数太多;二是 64×64 已经能保留足够分辨率的故障特征,计算量小好几个量级。这里需要说明,输入尺寸的确定是基于我自己的实验数据特性做的常见选择,不同数据集可能需要微调,但 64×64 是个性价比很高的起点。

4. 完整工程流程:从原始信号到诊断结果

4.1 数据准备与预处理

我手里的数据是轴承故障模拟实验台采集的振动信号,采样率 12kHz,包含正常、内圈故障、外圈故障、滚动体故障四种状态。原始数据是连续的长信号,不能直接丢给网络,要切样本。我的切法是这样:

fs = 12000; sampleLen = 1024; % 每个样本点数 stepLen = 512; % 重叠步长 samples = {}; labels = {}; for i = 1:numel(allSignals) sig = allSignals{i}; label = labelsRaw{i}; numSamples = floor((length(sig) - sampleLen) / stepLen) + 1; for j = 1:numSamples startIdx = (j-1) * stepLen + 1; samples{end+1} = sig(startIdx:startIdx+sampleLen-1); labels{end+1} = label; end end

重叠 50% 是为了数据增强,样本量直接翻倍。对于深度学习来说,样本量永远是多多益善,只要保证训练集和测试集来自不同时间段的数据,重叠取样不会造成信息泄漏。

每个样本长度 1024 点,在 12kHz 采样率下大约是 85ms,对于轴承故障特征频率(通常在几十到几百赫兹)来说,足够包含多个完整故障周期。

4.2 DWVD 时频图批量生成与预处理

对每个样本做 DWVD,得到的是一个二维复数矩阵,取模之后是能量分布。这一步我单独写了个批处理脚本,一次性把全数据集转成图像并保存为 .mat 文件,避免每次训练都重算一遍时频变换。

for i = 1:numel(samples) x = samples{i}; [tfr, ~] = myDWVD(x, fs); tfrImg = mat2gray(abs(tfr)); % 归一化到 [0,1] tfrImg = imresize(tfrImg, [64, 64]); % 统一尺寸 imgs(:,:,1,i) = tfrImg; end

注意 mat2gray 这一步很关键,直接把幅值线性归一化到 0~1,送入网络之前不需要再做标准化。做过归一化之后,不同样本之间的亮度差异被抹平,网络学起来更容易收敛。

4.3 MCNN 网络搭建与训练配置

用 MATLAB 深度学习工具箱,网络搭建可以直接用 layerGraph:

lgraph = layerGraph(); % 输入层 lgraph = addLayers(lgraph, imageInputLayer([64 64 1], 'Name', 'input')); % 多尺度卷积块1 conv1_1 = convolution2dLayer(1, 32, 'Name', 'conv1_1', 'Padding', 0); conv1_3 = convolution2dLayer(3, 32, 'Name', 'conv1_3', 'Padding', 1); conv1_5 = convolution2dLayer(5, 32, 'Name', 'conv1_5', 'Padding', 2); lgraph = addLayers(lgraph, conv1_1); lgraph = addLayers(lgraph, conv1_3); lgraph = addLayers(lgraph, conv1_5); % 并联拼接 concat1 = concatenationLayer(3, 3, 'Name', 'concat1'); lgraph = addLayers(lgraph, concat1); lgraph = connectLayers(lgraph, 'input', 'conv1_1'); lgraph = connectLayers(lgraph, 'input', 'conv1_3'); lgraph = connectLayers(lgraph, 'input', 'conv1_5'); lgraph = connectLayers(lgraph, 'conv1_1', 'concat1/in1'); lgraph = connectLayers(lgraph, 'conv1_3', 'concat1/in2'); lgraph = connectLayers(lgraph, 'conv1_5', 'concat1/in3'); % 后面跟上BN、ReLU、池化、第二个多尺度块、全局平均池化、全连接、softmax

训练配置我推荐这样设:

options = trainingOptions('adam', ... 'InitialLearnRate', 1e-3, ... 'MaxEpochs', 30, ... 'MiniBatchSize', 32, ... 'ValidationData', {valImgs, valLabels}, ... 'ValidationFrequency', 10, ... 'Plots', 'training-progress', ... 'Shuffle', 'every-epoch', ... 'LearnRateSchedule', 'piecewise', ... 'LearnRateDropFactor', 0.5, ... 'LearnRateDropPeriod', 10);

初始学习率 1e-3 是经验值,对于图像分类任务来说比较稳。如果发现 loss 震荡不收敛,先降到 5e-4 试试,而不是去改网络结构。MiniBatchSize 32 是内存和梯度稳定性之间的平衡,我的显卡 6G 显存跑这个尺寸没压力。

4.4 结果评估与可视化

训练完之后,我习惯先看混淆矩阵,而不是只看准确率。准确率只能告诉你整体行不行,混淆矩阵能告诉你哪两类容易互相认错。我遇到的情况是滚动体故障和内圈故障的混淆率比较高,原因也合理——两者产生的冲击特征在时频图上有相似性,尤其是当滚动体故障进入早期阶段时,特征幅度弱,和噪声的边界更模糊。

评估代码核心部分:

YPred = classify(net, testImgs); accuracy = mean(YPred == testLabels); figure; plotconfusion(testLabels, YPred);

另外我还习惯把网络最后一层全连接输出的特征向量拿出来,用 t-SNE 降维到二维画散点图。如果同一类聚成一团、不同类分得开,说明特征学得好;如果混在一起,说明网络没学到有效区分,这时候就该回头看看时频图质量和网络结构了。

5. 调试过程实录:那些年我踩过的坑

5.1 DWVD 计算速度慢到怀疑人生

裸写的双重循环 DWVD 跑 1024 点信号,一个样本要好几秒。几千个样本跑下来,得几个小时。后来我优化了中间的相关运算部分,改成了矩阵化操作,速度提升明显。对于时间紧的项目,建议直接用 MATLAB 的 DSP 工具箱里的现成函数,或者先降采样缩短信号长度再算。时频图的尺寸和频率分辨率本身就是权衡,不需要无脑追高分辨率。

5.2 交叉项没压住,网络学了一堆“幻觉特征”

最开始我直接拿裸 WVD 的输出去训练网络,训练曲线很好看,但一换测试数据立刻拉胯。原因就是模型把交叉项的伪特征当成了故障特征来学,换了数据交叉项的位置和形态全变了,模型自然就失效了。后来加上核函数平滑,把交叉项压低之后,测试准确率明显回升。这一条我建议好好记住:时频分析这一步的输出质量,再怎么强调都不过分,宁可在预处理阶段多花时间调核函数参数,也别拿脏数据硬训网络。

5.3 类别不均衡导致的“假准确率”

早期实验里正常样本远多于故障样本,网络学出来的结果看着准确率有 95%,实际上故障样本几乎全分错,准确率是被多数类拉高的。后来我用混淆矩阵发现问题,重新对少数类做了过采样,保证每类样本数量基本一致,才拿到真正可用的模型。评估故障诊断模型,一定要分清楚“整体准确率”和“各类准确率”,后者才是工程上真正关心的指标。

5.4 时频图分辨率的取舍

我试过 128×128 的输入,准确率只提升了一两个百分点,训练时间翻倍。也试过 32×32,准确率掉了五六个点。64×64 是性价比的甜点位。这个结论针对的是我实验里的数据和故障类型,如果你的故障特征本身非常细微,可能需要更高分辨率,但这个思路值得参考——先从小到大试一遍,找到准确率变化曲线变平缓的位置,就是合适的分辨率。

6. 换数据、换场景时,这套方案怎么调整

没有一套方案是放之四海而皆准的。DWVD + MCNN 这套方法,用的场景是旋转机械振动信号,但如果要迁移到其他场景,有几个地方需要重新考虑。

第一个是采样率和信号长度的匹配。我的样本是 1024 点 @12kHz,约 85ms。如果你的设备转速很低,故障特征频率只有几赫兹,85ms 里可能连一个完整周期都装不下,样本长度就得加长。反过来高频故障信号,样本长度太长反而让时频图上的特征被压缩,也要调。

第二个是故障类型的区分度。如果不同故障类型在时频图上的表现本身就非常接近,单纯靠图像分类网络很难区分,这时候可以考虑在信号预处理上下功夫,比如先做带通滤波突出共振频带,再做包络解调,最后再送 DWVD。包络分析是轴承故障诊断的老牌方法,和时频分析结合能进一步提升信噪比。

第三个是网络的迁移学习。如果换了新的设备或新的故障类型,但和原有数据集有一定的相似性,可以复用之前训练好的网络作为预训练模型,只冻结前面的卷积层,重新训练后面几层。这样能大幅减少训练数据需求,收敛也快得多。我试过一次,数据量只有原来的三分之一,微调之后也能达到接近从头训练的效果。

7. 实操中的一点个人体会

这套 DVMCNN 方案我跑过轴承数据、也尝试迁移到齿轮箱数据上,整体感受是:时频分析和深度学习的组合拳,确实比“手工特征 + 分类器”的老路子省心,也比“裸信号直接送网络”的效果好——因为时频图等于把人类对故障机理的理解提前缝进了特征里,网络不用自己去摸索这个先验知识。

给后来者几个实在的建议:一,不要跳过核函数参数调优这一步,这是 DWVD 能不能用的分水岭;二,第一次跑通后,先别急着调网络结构,把数据预处理、样本划分、评估指标这几件事搞严谨,效果提升往往比换网络架构更显著;三,训练果不好先看混淆矩阵,别只看整体准确率;四,严格区分训练集和测试集的时间段,同一段信号重叠取样会让测试集失去意义。

最后分享一个小细节。我在生成时频图像集时,顺手把每张图的能量均值、峰值频率也存了一份。虽然 MCNN 自己能学特征,但这些人工统计量在后续做模型可解释分析、找误分类原因的时候特别有用。有一次排查误分类样本,就是靠这些统计量发现某个样本的时频图能量峰值异常低,再追查下去发现是这段数据采集时传感器松动。这些边缘信息,有时候比网络本身更能说明问题。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询