尧图精选

CNN-LSTM轴承故障诊断:变工况下的Python实战与避坑指南

🕒 发布时间:2026/10/1 19:22:42 📁 来源:尧图网络
简介这份资源面向机械故障诊断与深度学习方向的课程设计、毕业设计及入门研究者提供一套基于CNN-LSTM的滚动轴承故障诊断完整Python实现方案。课题覆盖外环、内环与滚动体三类损伤并对应三种轴承规格尺寸共形成九种故障类别实验工况为3马力负载、约1730转/分钟可用于学习振动信号特征提取与深度学习分类建模。资源包共30个文件约56.3MB包含csv与mat格式的原始及处理后数据、pth预训练模型权重、py训练与测试脚本、ipynb演示笔记、m数据转换脚本、xlsx结果记录及png方法示意图另附md说明文档便于快速复现与二次开发。目前已有53人学习下载。读者可据此掌握从数据读取、重叠采样、模型搭建到训练评估的完整流程并借助预训练模型与工具脚本缩短调试周期适合作为轴承故障诊断项目的参考模板。1. 轴承故障诊断为什么总在变工况下翻车CNN-LSTM 能补上哪块短板产线上滚动轴承的振动信号正常时安静得像背景噪声一旦内圈剥落或外圈裂纹出现冲击成分会周期性冒出来。麻烦在于转速一变、负载一调原本训练好的模型准确率能从 98% 掉到 70% 以下这是很多做设备健康管理的工程师都踩过的坑。基于 CNN-LSTM 的轴承故障诊断系统核心思路就是用卷积层从原始振动或时频图里抽局部冲击特征再用 LSTM 记住这些特征在时间轴上的演化规律最后输出故障类别。它适合手里有振动数据、想用 Python 快速搭一套可复现诊断流程的人也适合已经用过 FFT 加 SVM 但发现泛化不够、想升级到深度学习方案的从业者。完整源码、预训练模型和项目文档的价值不在于代码多长而在于把数据切分、模型结构、训练策略和推理接口这四件事固定下来让你换一台设备时只改配置不改骨架。2. CNN-LSTM 做轴承诊断的选型逻辑与数据准备2.1 为什么不是纯 CNN 或纯 LSTM纯 CNN 在轴承故障诊断里很常见把振动信号转成灰度图或者直接一维卷积都能拿到不错的分类精度。但它的短板是感受野固定对冲击间隔这种跨时间的依赖关系建模偏弱。纯 LSTM 反过来能记住长序列里的周期模式可它对局部突变不敏感而轴承早期故障恰恰表现为短时冲击。CNN-LSTM 串起来前面几层卷积负责提局部冲击包络后面 LSTM 负责跟踪冲击重复频率两者互补。常见做法是两层一维卷积加池化接一层 LSTM再全连接分类。如果你的数据是手工特征表而不是原始波形那 CNN 部分可以换成全连接编码器但那就不是这个标题讲的东西了。2.2 数据从哪来、怎么切公开数据集里CWRU 轴承数据是入门最常用的驱动端和风扇端各有正常、内圈、外圈、滚动体四类采样率 12kHz 或 48kHz。实际产线上拿到的往往是连续采集的长信号需要自己切窗。窗口长度一般取 1024 或 2048 点重叠率 50% 左右这样既能覆盖一个完整冲击周期又不会让样本太少。标签按文件段来打不要按单点打否则同一段信号被切到训练集和测试集会造成泄漏。下面这段代码演示从原始 mat 文件切窗并做归一化的最小流程。import scipy.io as sio import numpy as np def load_and_window(mat_path, label, win1024, step512): # 读取 CWRU 的 DE 通道数据键名通常是 X105_DE_time data sio.loadmat(mat_path) key [k for k in data.keys() if DE_time in k][0] signal data[key].flatten() windows, labels [], [] for start in range(0, len(signal) - win, step): seg signal[start:start win] # 按段做零均值单位方差避免幅值差异干扰 seg (seg - seg.mean()) / (seg.std() 1e-8) windows.append(seg) labels.append(label) return np.array(windows), np.array(labels)逻辑说明win是窗口长度step是滑动步长两者决定样本数量和重叠度。归一化放在切窗之后、按段做不要对整条长信号做全局归一化否则训练集和测试集的统计量会混在一起。参数上12kHz 数据用 1024 点窗口大约覆盖 85ms足够包含一个冲击周期如果转速很低可以加到 2048。标签用整数编码后面接sparse_categorical_crossentropy或CrossEntropyLoss都方便。2.3 训练集、验证集、测试集怎么分才不虚高很多人把同一段信号切出来的窗随机打乱后按 7:2:1 分结果测试准确率 99%换一台设备直接崩。正确做法是按采集段或按工况分比如用负载 0 和 1 的数据训练负载 2 和 3 的数据测试这样测出来的才是跨工况泛化能力。如果数据量够再留一段完全没见过的转速做最终验证。预训练模型如果是在 CWRU 上训的拿到你自己的数据上至少要先做一次微调不要直接推理。3. 用 Python 搭 CNN-LSTM 诊断模型结构、训练与推理3.1 模型结构怎么定卷积核、池化、LSTM 单元数一维卷积部分第一层卷积核大小取 64 左右步长 8 或 16这样能快速降采样并保留冲击包络第二层卷积核大小 16步长 2。池化用最大池化窗口 2。LSTM 单元数一般 64 到 128层数一层就够两层容易过拟合。全连接层前加 Dropout比率 0.3 到 0.5。下面是一个 PyTorch 版本的最小结构Keras 版本把对应层换掉即可。import torch import torch.nn as nn class CNNLSTM(nn.Module): def __init__(self, num_classes10): super().__init__() self.conv nn.Sequential( nn.Conv1d(1, 16, kernel_size64, stride16, padding24), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(16, 32, kernel_size16, stride2, padding7), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2) ) self.lstm nn.LSTM(input_size32, hidden_size64, num_layers1, batch_firstTrue) self.fc nn.Sequential( nn.Dropout(0.4), nn.Linear(64, num_classes) ) def forward(self, x): # x: (batch, 1, 1024) x self.conv(x) # (batch, 32, T) x x.permute(0, 2, 1) # (batch, T, 32) out, _ self.lstm(x) return self.fc(out[:, -1, :])逻辑说明Conv1d的padding要手动算保证输出长度是整数。permute把通道维换到最后一维因为 LSTM 默认要求(batch, seq, feature)。取out[:, -1, :]是取最后一个时间步也可以做平均池化。参数上hidden_size不要超过 128否则小数据集上很容易记住噪声。BatchNorm 放在卷积后、激活前对振动信号这种幅值变化大的数据很关键。3.2 训练循环里必须盯住的三个量训练时不要只看 loss要同时看训练准确率、验证准确率和验证 loss 的走势。如果训练准确率一直涨、验证准确率早早就平了说明过拟合加 Dropout 或减 LSTM 单元数。如果两者都上不去先检查归一化和标签有没有错。学习率用 1e-3 配 Adam每 20 个 epoch 降一半。下面是一个简化的训练片段。from torch.utils.data import DataLoader, TensorDataset import torch.optim as optim X_train torch.tensor(X_train, dtypetorch.float32).unsqueeze(1) y_train torch.tensor(y_train, dtypetorch.long) loader DataLoader(TensorDataset(X_train, y_train), batch_size64, shuffleTrue) model CNNLSTM(num_classes10) opt optim.Adam(model.parameters(), lr1e-3) scheduler optim.lr_scheduler.StepLR(opt, step_size20, gamma0.5) criterion nn.CrossEntropyLoss() for epoch in range(80): model.train() for xb, yb in loader: opt.zero_grad() loss criterion(model(xb), yb) loss.backward() opt.step() scheduler.step() # 每个 epoch 后在验证集上算准确率保存最优权重逻辑说明batch_size取 64 是振动信号分类的常用值数据少可以降到 32。StepLR每 20 轮降一次学习率避免后期震荡。保存权重时按验证准确率最高的那一轮存不要按最后一轮存。预训练模型如果已经给了权重文件加载后先冻结卷积层训几轮 LSTM再解冻整体微调这样小样本上更稳。3.3 推理接口怎么写才方便换设备推理时最容易出问题的是输入长度和归一化方式不一致。把切窗和归一化封装成一个函数训练和推理共用。输出用 softmax 转成概率再取 argmax 给类别。如果要做在线监测可以每次取最新 1024 点滑窗步长设成 256连续多次预测同一类别再报警避免单次误报。def predict(signal, model, win1024, step256): model.eval() probs [] for start in range(0, len(signal) - win, step): seg signal[start:start win] seg (seg - seg.mean()) / (seg.std() 1e-8) x torch.tensor(seg, dtypetorch.float32).view(1, 1, -1) with torch.no_grad(): p torch.softmax(model(x), dim1) probs.append(p.numpy()) return np.concatenate(probs, axis0)逻辑说明step越小报警越灵敏但计算量越大。view(1, 1, -1)里的两个 1 分别是 batch 和通道。返回的是每个窗口的概率矩阵后面可以按时间做投票。注意推理时的归一化必须和训练时完全一致否则精度会莫名其妙掉一截。4. 避坑与排查轴承诊断项目里最容易翻车的五件事4.1 现象测试准确率 99%换负载直接掉到 60%原因训练集和测试集来自同一段连续信号切窗时重叠部分把测试样本泄漏进了训练集。解决按采集段或按工况划分数据集同一段信号只能出现在一个集合里。如果数据文件本身按负载命名直接按文件名分组。4.2 现象训练 loss 不降准确率一直在随机水平原因标签编码和损失函数不匹配比如标签是 one-hot 却用了CrossEntropyLoss或者归一化时把整条信号减了全局均值导致数值溢出。解决检查标签形状CrossEntropyLoss要整数标签归一化按窗口做加1e-8防止除零。4.3 现象模型在验证集上波动很大每次训练结果差很多原因小数据集上 batch 顺序影响大或者学习率太高。解决固定随机种子batch_size适当调大学习率从 1e-3 降到 5e-4 试。另外 LSTM 的初始化对结果也有影响可以多跑几次取平均。4.4 现象推理时单次预测跳变严重报警频繁误触原因滑窗步长太小相邻窗口高度相关单次预测受噪声影响大。解决增大步长到 256 或 512或者对连续 5 个窗口做多数投票再输出。在线监测里还可以加一个置信度阈值低于阈值不报警。4.5 现象加载预训练模型后精度远低于文档里写的数字原因预训练模型用的采样率、窗口长度或归一化方式和你的数据不一致。解决先确认预训练模型的输入规格把自己的数据重采样或重新切窗到同一规格。如果规格对不上冻结卷积层只训分类头也能拿到一个可用的基线。5. 把 CNN-LSTM 诊断系统用起来从单机脚本到产线验证的进阶技巧模型训完只是第一步真正要投入产线得解决三件事推理速度、模型更新和误报抑制。推理速度上如果用的是工控机没有 GPU可以把卷积层用 ONNX Runtime 跑LSTM 部分保留 PyTorch或者直接导出整个模型到 ONNX实测在 i5 上单窗口推理能压到 10ms 以内。模型更新上不要每次重新训用增量微调新数据进来后只训最后全连接层和 LSTM卷积层冻结学习率设 1e-4跑 10 个 epoch 就够。误报抑制上除了投票还可以加一个基于包络谱的规则校验比如 CNN-LSTM 判为外圈故障时同时检查包络谱在故障特征频率处是否有峰值两个条件都满足才报警。验证方法上我一般会留一段完全没参与训练的数据做盲测按时间顺序推理画一张预测类别随时间变化的图看报警是否集中在故障发生之后。如果故障发生前就频繁报警说明模型学到了工况相关的伪特征需要检查数据划分。下面这个表格是我在几个项目里总结的参数起点可以直接抄。参数推荐值说明窗口长度102412kHz 采样下约 85ms滑窗步长512训练/ 256推理训练重叠 50%推理更密卷积核第一层 64第二层 16第一层抓冲击第二层抓包络LSTM 单元数64超过 128 小数据易过拟合Dropout0.4加在 LSTM 后、全连接前学习率1e-3每 20 轮减半Adam 优化器Batch size64数据少降到 32最后说一个我自己的习惯每次换新设备先不急着训模型而是把正常数据切窗后跑一遍预训练模型看输出概率分布是不是集中在某一类。如果正常数据被大量判成故障说明域差异太大这时候要么重新采集带标签的故障样本要么至少做一次卷积层微调。这个检查花不了十分钟但能省掉后面几天的无效调参。希望帮到你。本文还有配套的精品资源点击获取
上一篇/下一篇内容由系统自动关联 返回资讯列表 →