ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

轴承故障诊断100%精度可复现:振动信号转图像与CNN实现详解

轴承故障诊断100%精度可复现:振动信号转图像与CNN实现详解 简介这份PDF是一篇面向机械工程、设备故障诊断研究人员及深度学习初学者的学术论文聚焦滚动轴承故障诊断难题。作者提出将振动信号经分帧、加窗、DFT与图像编码构建振谱图并设计深度卷积神经网络自动提取故障特征、完成模式识别克服传统奇异值分解、经验模态分解等方法表征信息不完整的问题。资源共1个文件为PDF格式压缩包大小约1.28MB内容包含原理阐述、网络结构设计与训练流程并以美国凯斯西储大学公开实测振动数据验证识别准确率达到100%方法具备工程应用前景。已有571人学习该资料适合作为故障诊断与深度学习交叉领域的方法参考。1. 卷积神经网络做轴承故障诊断这篇论文为什么值得照着复现你打开这篇论文的时候别先去看那张 100% 的精度表先想一个反直觉的结论把滚动轴承的振动信号转成一张图像再用卷积神经网络做分类测试集上能做到全部识别正确。它没有发明什么新网络也没有堆复杂特征而是用短时傅里叶变换把一维振动信号变成“振谱图”然后交给一个五卷积三全连接的 DCNN 去学。数据用的是美国凯斯西储大学公开轴承数据集实验对象是内圈四种故障尺寸加正常轴承识别精度 100%。这份 PDF 值得下载的地方在于参数给得具体数据点数 1024、帧长 192、帧重叠比例 7/8网络结构图里连每层输出尺寸都标了很适合正在做旋转机械故障诊断、想把振动信号转图像做深度学习的工程师或研究生。照着复现一遍你就知道所谓 100% 是怎么来的以及哪些位置最容易翻车。2. 从时域到振谱图STFT 是振动信号特征提取的关键一环轴承故障诊断的老路子是先采振动信号再用经验公式从信号里挖一个或几个特征最后交给支持向量机、K 近邻这类分类器。这套流程不缺理论缺的是信息完整性轴承从正常到损伤信号里同时混着周期冲击、转频调制和噪声单一特征很难把所有变化装进去。论文引用的奇异值分解、多尺度模糊熵分析、经验模态分解都是这一个思路效果常常卡在某一类故障能识别、另一类就含糊的尴尬位置。2.1 为什么不能把轴承振动信号整体拿去傅里叶变换滚动轴承运行时故障点每经过承载区就会产生一次冲击这个冲击的幅度和相位会随转频发生变化。振动信号整体看是非平稳的均值、方差、频率成分都在随时间变化。如果直接把整段信号做一次 FFT得到的是一个平均频谱冲击发生的时间位置完全丢失早期微弱故障很容易被淹没在平稳分量里。论文抓住了轴承振动信号“整体非平稳、短时平稳”的特点这是整条技术路线能立住的前提。这里有一个常见误区很多人拿到振动信号第一反应就是算频谱但频谱只能告诉你“有哪些频率”不能告诉你“这些频率什么时候出现”。故障冲击是瞬态事件时间信息恰恰是区分正常冲击还是故障冲击的关键线索所以必须做时频分析。2.2 短时平稳与三个 STFT 参数的关系短时傅里叶变换的做法是把一段振动信号切成若干帧每帧短到可以近似看成平稳信号然后对每一帧加窗再做离散傅里叶变换最后把各帧频谱按时间顺序拼起来。论文里给出的参数组合是数据点数 1024、帧长 192、帧重叠比例 7/8这不是随手写的是做了 115 次训练实验扫出来的。先说物理含义。采样频率是 12 kHz帧长 192 点对应 16 ms 左右的一段信号在这么短的时间内轴承振动可以视为平稳每帧做完 DFT 后取正频率部分频点数是 T/21也就是 97 个。帧长决定频率分辨率帧越长频率分辨越细重叠比例决定时间分辨率重叠越多帧与帧之间越平滑。重叠 7/8 这个值在普通频谱分析里很少见常规做法是 50% 重叠就够。论文把它拉到 7/8意味着相邻帧只滑动 24 个采样点谱图时间轴被磨得很细。这样做的好处是 CNN 看到的纹理更连续不会因为帧边界错动出现断裂感代价是计算量变大但在 12 kHz 采样下完全可接受。2.3 加窗不是可选项是必须项DFT 隐含假设信号是周期的但截取的一帧信号两端往往不是连续的直接做变换会在频域产生泄漏把真实的窄带峰值抹成一片旁瓣。论文用汉明窗来处理这个问题窗函数公式为ω(t)0.54-0.46cos[2πt/(T-1)]窗长与帧长一致加窗后再做 DFT。汉明窗的特点是主瓣稍宽但旁瓣衰减快适合振动信号这种能量集中在若干频带的场景。代码里可以直接用 SciPy 的 hamming也可以照公式自己写效果相同。2.4 振谱图与手工特征的本质区别把振谱图喂给卷积神经网络本质上把故障诊断从“设计特征”换成了“让网络自己找特征”。CNN 的卷积核天然适合捕捉图像里的局部能量斑块和纹理这些纹理对应的正是故障冲击在时频面上的分布。论文对比了此前几类深度学习方法深度信念网络做到 92% 以上堆栈自动编码器只取频域信息做到 99%包络谱加高斯受限玻尔兹曼机做到 93.5%它们要么只用频域要么只用包络没有把时域和频域联合起来。振谱图同时给出频率、时间、能量三个维度CNN 对这三类信息一起学习效果自然比单模态特征更好这也是论文能够把普通轴承故障诊断推到 100% 的核心原因。实际工程里有人会问为什么不换连续小波变换小波尺度轴和母小波选择会引入新的超参数复现成本更高STFT 只有三个参数每个都有明确物理含义更适合做系统性调参。这个项目追求的是用最少的玄学拿到可复现的好结果。3. 把振动波形转成 227×227 图像六步处理与可抄的 Python 代码论文把振动信号转成振谱图的过程拆成六步分帧、加窗、DFT、频谱能量密度计算、像素颜色映射、谱线重组与尺度变换。下面是按论文公式整理的实现直接可以跑通。3.1 六步流程与关键参数先记住一组参数数据点数 N1024帧长 T192重叠点数 S168帧滑动步长 aT-S24。按论文式(1)帧数 H(N-T)/a1算出来是 35。每帧 DFT 后取正频率部分频点数 KT/2197。所以一张原始振谱图的尺寸是 35×97远小于网络输入的 227×227后续需要尺度变换。3.2 分帧、加窗与 DFT 的代码实现import numpy as np def hamming_window(n): # 论文式(3)窗长与帧长一致 return 0.54 - 0.46 * np.cos(2 * np.pi * np.arange(n) / (n - 1)) def framing(signal, frame_len192, hop24): # 式(1)H(N-T)/(T-S)1hopT-S n_frames 1 (len(signal) - frame_len) // hop frames [] for i in range(n_frames): start i * hop frames.append(signal[start:start frame_len]) return np.stack(frames) def frame_spectrum(frame, win): # 加窗后做DFTrfft只保留0~fs/2共T/21个频点 return np.abs(np.fft.rfft(frame * win))代码里的hop对应论文中的 a即帧滑动步长。rfft返回的长度是T/21正好等于 K不需要再做截断。framing用的是整数除法取整保证最后一帧不会越界如果信号长度不够返回的帧数会比理论值少后面会提到这是个坑。3.3 能量对数化与像素颜色映射DFT 得到的幅度谱需要转成能量密度论文式(7)和式(8)的做法是取幅度平方再取 10 倍对数等价于对幅度取 20 倍对数。直接对原始能量做线性映射有一个问题冲击信号动态范围很大个别极值会把整张图的灰度拉爆。论文式(9)用的是最大最小值线性归一化到 [0,255]工程上我习惯加一个分位数裁剪更稳。def spectrum_to_image(mags, low2, high98): # 能量密度转dB加eps防止log0 power_db 10 * np.log10(mags ** 2 1e-10) vmin, vmax np.percentile(power_db, low), np.percentile(power_db, high) norm (power_db - vmin) / (vmax - vmin) return np.clip(norm, 0, 1) * 255low2, high98的意思是取 2% 到 98% 分位数作为映射边界低于下界的裁成 0高于上界的裁成 255。这样既保留能量相对关系又不会让一两个强冲击点占满整个灰度范围。如果不加分位数图要么黑乎乎一片要么刺眼过曝CNN 训练时会非常不稳定。3.4 谱线重组、尺度变换与三通道输入把所有帧的频谱线按时间顺序堆叠得到的就是初始振谱图尺寸是 H×K。接下来要缩放到 227×227这是论文设计网络时的固定输入尺寸对应经典 AlexNet 的输入规格。要注意这里不是 224是 227。import cv2 def signal_to_spectrogram(signal, frame_len192, hop24): frames framing(signal, frame_len, hop) win hamming_window(frame_len) mags np.array([frame_spectrum(f, win) for f in frames]) img spectrum_to_image(mags) # 初始图(H, K)(35,97)resize到(227,227) img_227 cv2.resize(img, (227, 227), interpolationcv2.INTER_LINEAR) # 单通道复制成三通道匹配网络输入 img_rgb np.stack([img_227] * 3, axis-1).astype(np.uint8) return img_rgbcv2.resize的默认插值方式对频谱图来说够了不需要用太高级的插值。复制成三通道是因为论文里网络输入标注是 227×227×3CNN 第一层卷积核对应三通道颜色通道在这里没有额外物理含义只是为了对齐输入格式。实际操作中也可以保持单通道并把第一层卷积的输入通道改成 1但那样就和论文结构不一致。# 调用示例CWRU数据里一帧信号长度1024 spectrogram signal_to_spectrogram(signal_data[:1024]) print(spectrogram.shape) # (227, 227, 3)生成的振谱图可以直接作为训练样本标签按故障类别映射。整条预处理链路里最容易出错的是尺度变换前的尺寸确认最好在signal_to_spectrogram入口处打印一下frames.shape确保 H 和 K 是预期值。4. 五卷积三全连接DCNN 结构与每层参数怎么推算论文设计的深度卷积神经网络包含 1 层输入层、5 层卷积层C1 到 C5和 3 层全连接层F6 到 F8中间配了 3 个最大值池化层。网络整体沿用了 AlexNet 的骨架但把输入尺寸和输出神经元数按轴承故障诊断任务做了调整。这一章把每层参数梳理成表并给出尺寸推算方法。4.1 网络整体结构与参数表论文原文只给了每层输出尺寸没有逐层标注卷积核大小和步长但可以根据输出尺寸反推并用 AlexNet 常见配置补齐。下表是复现时使用的结构和论文图 3 的输出尺寸完全一致。层名类型核大小 / 池化核paddingstride输出尺寸Input输入---227×227×3C1卷积×9611×110496×55×55P1最大值池化3×30296×27×27C2卷积×2565×521256×27×27P2最大值池化3×302256×13×13C3卷积×3843×311384×13×13C4卷积×3843×311384×13×13C5卷积×2563×311256×13×13P5最大值池化3×302256×6×6F6全连接---4096F7全连接---4096F8全连接Softmax---5这里的 5 对应论文实验里的 5 类标签正常轴承加上 4 种内圈故障尺寸。如果换成外圈、滚动体等多部位分类F8 的神经元数也要同步改。4.2 卷积与池化尺寸计算公式卷积层输出尺寸按式(12)计算S(fs)k×[((H2×pad-w)/stride)1]×[((K2×pad-h)/stride)1]其中 H、K 是输入特征图尺寸w、h 是卷积核尺寸stride 是步长pad 是边缘扩展。以 C1 为例输入 227核 11步长 4pad 为 0输出 (227-11)/4155正好对上 96×55×55。池化层公式同理只是把卷积核换成池化核。论文选择最大值池化池化核尺寸是 3×3步长 2输出尺寸 (55-3)/2127也就是 P1 层的 96×27×27。最大值池化在振动信号振谱图上的意义是保留局部区域里能量最强的点对应故障冲击的显著频带比平均池化更能突出冲击特征。# 仅示意卷积部分结构核与pad对照上表 net_conv nn.Sequential( nn.Conv2d(3, 96, 11, stride4, padding0), # 227-55 nn.MaxPool2d(3, stride2), # 55-27 nn.Conv2d(96, 256, 5, padding2), # 27-27 nn.MaxPool2d(3, stride2), # 27-13 nn.Conv2d(256, 384, 3, padding1), # 13-13 nn.Conv2d(384, 384, 3, padding1), nn.Conv2d(384, 256, 3, padding1), nn.MaxPool2d(3, stride2) # 13-6 )这段代码只写了卷积池化部分省略全连接层。每一层的注释里都标了尺寸变化方便逐层核对。注意 PyTorch 的 padding 参数和公式里的 pad 含义一致都是输入边界扩展的像素数。4.3 用公式反推核对原文结构复现时最怕的是照着网上某一版 AlexNet 抄结果尺寸对不上。建议拿到论文图 3 后先把每层输出尺寸抄下来再用上面的公式逐层反推C1: (227-11)/4 1 55 P1: (55-3)/2 1 27 C2: (272*2-5)/1 1 27 P2: (27-3)/2 1 13 C3: (132*1-3)/1 1 13 P5: (13-3)/2 1 6反推过程能发现很多隐藏问题。比如 C2 输入 27卷积核 5如果忘记 pad2输出会变成 23后面全乱。我就是在这个环节吃过大亏后来养成一个习惯每一行代码后面都写注释标明输出尺寸预期值跑之前先用纸笔算一遍。4.4 训练与收敛细节网络参数通过前向传播和误差反向传播确定论文采用随机梯度下降法调整权重。分类输出层用 Softmax损失函数用交叉熵这是多分类问题的标准配置。论文没有给出学习率、batch size、epoch 数但根据图 9 的曲线训练轮数不需要太多模型精度随轮数提升到 100%误差迅速收敛到接近零。我复现时常用 batch size 64、初始学习率 0.01 并随训练轮数衰减激活函数用 ReLU。论文式(11)里写的是 Sigmoid 型函数但 ReLU 在实际训练里收敛更快梯度消失问题更少。在这里说明一下这不是论文原话是工程复现的常见做法。如果你发现训练 loss 降不下去优先检查学习率是不是太大或太小其次检查数据归一化是否做干净了。5. 复现避坑排查轴承故障诊断最容易翻车的五个位置这一章写我自己复现这类“信号转图像 CNN”论文时的真实踩坑记录每条按现象、原因、解决三个层次说清楚。5.1 训练集精度奇高、测试集翻车先查数据划分现象训练集 Accuracy 一直往 99% 以上走测试集一换新样本就掉到 80% 左右。原因CWRU 数据集每类故障只有几十秒信号如果随机切成小段后再随机洗牌划分训练集和测试集训练集和测试集里会混入来自同一段连续信号的相邻片段。这些片段高度相关模型本质上在背样本编号而不是学故障特征。解决严格按论文表 1 的方式做序列级划分。每类故障取 117 段信号前 97 段做训练后 20 段做测试划分前不要打乱原始顺序。我一般还会打印两个集合各自的起始索引确保完全没有交集再开始训练。5.2 振谱图黑乎乎一片或过曝刺眼能量归一化没做对现象生成的振谱图要么全黑要么亮成一片输入网络后 loss 根本不降。原因直接对 DFT 幅度取对数时没有加保护值log(0) 产生负无穷或者用全局最大值做归一化一个强冲击点就把整个动态范围拉高其余细节全被压到低灰度区。解决先对能量谱加一个极小的 eps 再取 dB然后分位数裁剪到 [2, 98] 再做 min-max 映射最后转成 uint8。这套做法和论文式(9)的纯线性映射不完全一样但工程上更稳。如果你坚持用论文原式至少要在分子分母都加同一个极小值防止除零。5.3 图像尺寸对不上报错帧数与频点数没算明白现象模型训练到第二个 epoch 时突然报 shape mismatch或者cv2.resize之前发现数组维度和预期不一致。原因帧数计算用了浮点除法或者信号长度不是 hop 的整数倍导致实际帧数比理论值少一帧。比如论文式(1)的 H(N-T)/(T-S)1如果 N 取 1024、T 取 192、重叠 7/8H35但如果你把整段信号直接传进去而不截断N 变了帧数自然对不上。解决固定输入长度 1024用整数除法n_frames 1 (len(signal) - frame_len) // hop切不完的尾部直接丢弃。生成振谱图后先print(img.shape)确认是 (35, 97)再做 resize。这个检查应该写进预处理函数里不要依赖肉眼。5.4 层与层之间维度崩掉卷积步长和 padding 配错现象前向传播跑到第二层或第三层时torch 直接报Expected 4D input或size mismatch维度算出来是负数。原因手工搭的网络某一层卷积核尺寸、padding 或步长写错例如 C3 用的是 3×3 核但忘了 pad113×13 的特征图会缩到 11×11后面全乱。解决每层都按公式手推一次并在代码里加断言。比如assert out_h 13, fC3 output height {out_h}跑前向时自动检查。这条断言能帮你把问题定位到具体层而不是面对一整屏的堆栈报错。5.5 标签体系混着用正文和表格里其实是两种标签现象训练到后期 loss 变成 NaN或者精度一直不上检查数据时发现标签分布完全不符合预期。原因论文里存在两套标签描述。表格里是“正常0内圈四种故障尺寸1 到 4”这是按故障程度分类正文里又写了“滚动体0、内圈1、正常2、外圈3、4”这是按故障位置分类。复现时如果混着用网络输出层 5 类语义就是乱的。解决开工前先确定你要做的是“故障位置分类”还是“故障尺寸分类”。CWRU 数据文件名里有轴承位置和故障直径建议写一个解析函数把文件名映射成唯一整数标签每一类打印样本数核对。把标签映射写进配置文件别在代码里硬编码数字。6. 三招验证你的 100% 是真学到了进阶检查与拿来即用的习惯验证一个故障诊断模型不能只看最终精度尤其当精度高到 100% 时更要怀疑它是不是在背样本。第一招训练和测试曲线一起看。论文图 9 左边是测试精度右边是训练和测试过程 loss 曲线复现时把每个 epoch 的 train loss 和 test loss 都记录下来。如果 test loss 在训练后期重新抬升说明已经过拟合如果 train loss 和 test loss 同步下降并稳定在零附近才算真正稳稳收敛。第二招把全连接层特征拉出来可视化。训练完成后取 F6 层输出的 4096 维特征降维到二维画散点图。正常学到的模型五类样本应该各自聚成团团间有明显间隔如果画出来所有点糊成一团说明网络只是在拟合训练标签没有形成可分的特征空间。第三招换转速做一次泛化测试。论文实验用的是 1797 r/min你可以把模型直接拿到 1772、1750、1730 r/min 的数据上预测看一下精度掉多少。掉得少说明模型学到了故障的通用时频特征掉得多说明它对转速工况敏感后续部署需要按转速分别建模。python train.py --data drive_end --rpm 1797 python eval.py --data drive_end --rpm 1772 # 跨转速泛化验证这三招做完再回头对照论文里的图 6、图 7、图 8你会发现论文里的每次调参都对应一个明确的精度变化而不是单纯撞运气。从那以后我每次复现这类“信号转图像 CNN”的论文都强制自己先过一遍这三步检查数据划分、检查特征可视化、检查跨工况泛化。宁可慢一天也不发一篇自己都说不清楚的注水结果。希望帮到你。本文还有配套的精品资源点击获取
返回列表