资讯动态

1DCNN轴承故障诊断源码全解析:免频谱图直接吃原始波形

发布时间:2026/10/26 16:56:14 来源:尧图企业网站定制
简介面向工业设备智能运维场景的深度学习实践资源围绕1DCNN轴承故障诊断的完整流程展开适合具备一定Python与机器学习基础的研究人员、算法工程师及机械故障诊断学习者。资源将源码组织为数据预处理、模型构建、训练测试、结果可视化等模块覆盖CWRUcnn模型封装、t-SNE降维展示、混淆矩阵评估等关键环节并配有正常、内圈、外圈、滚动体等故障模式的运行截图与说明文档便于复现从原始振动信号到故障类型判别的端到端流程。压缩包共50个文件以py源代码、png图像、txt标注与说明、xml工程配置为主辅以xls/xlsx结果表格整体约3.64MB目录结构便于按需查阅。目前已有426人学习下载适合作为快速上手1DCNN故障诊断任务的参考基线。1. 这套1DCNN轴承故障诊断源码不用做频谱图直接吃原始波形做轴承故障诊断的工程师很多人的第一反应是“先把振动信号做FFT或者STFT转成频谱图再喂给CNN”。但这套源码走的是另一条路用一维卷积神经网络1DCNN直接处理原始振动波形省掉了时频变换这一步输入就是传感器采出来的时间序列。它基于CWRU凯斯西储大学公开轴承数据集验证支持4分类和10分类两套标签体系从数据预处理、模型构建、训练、测试到t-SNE特征可视化全部脚本化一个main.py加一个config.py就能跑通整个流程。对于正在做设备健康管理、想用深度学习做故障诊断但不想从零搭网络的同学这套源码的价值在于网络结构是成熟的参数是调过的踩坑点集中在数据切分和标签对齐上。我拿到手第一件事就是把data目录下的预处理脚本和models目录下的网络定义拆开读了一遍下面把整个过程按实际动手顺序讲清楚。2. 数据准备CWRU原始振动信号到训练样本的完整流水线2.1 CWRU数据集的四类与十类划分逻辑源码里data目录下有raw_data原始数据配套两个标签文件annotations_4.txt和annotations_10.txt。这两个文件对应的是两种实验设置。4分类是故障诊断入门最常用的方案正常Normal、滚动体故障Ball、内圈故障Inner Raceway、外圈故障Outer Raceway也就是data目录下那几张PNG图片Roll Fault、Inner raceway Fault、Normal、Outer raceway Fault对应的四个状态。10分类则是把故障直径也作为类别信息加进去CWRU数据集中故障直径有0.007、0.014、0.021英寸三档每个位置三档加上正常状态一共10类这就是annotations_10.txt的来源。从源码结构看data_preprocess.py负责把raw_data里的原始振动信号切分成固定长度的样本dataset.py负责读取切好的样本和对应标签生成PyTorch的Dataset对象。这两步是整个流程里最容易翻车的地方因为CWRU原始数据是连续振动波形每条记录几万到几十万个采样点必须切窗才能喂给网络而切窗方式直接决定最终准确率是99%还是70%。2.2 data_preprocess.py滑窗切片的窗口长度与步长设置我一般跑这套流程时会先把data_preprocess.py单独执行一遍看它输出的样本格式。核心逻辑不复杂把每条原始振动记录按照固定窗口长度切分每段生成一个独立的训练样本。窗口长度和滑动步长是两个最关键的参数源码里通常取窗口长度在1024到2048之间步长设置分两种做法# data_preprocess.py 滑窗切片核心逻辑 import numpy as np def sliding_window_slice(signal, window_size1024, stride512): 对单条振动信号做滑窗切片 :param signal: 原始一维振动波形, numpy数组 :param window_size: 窗口长度, 决定单个样本包含的采样点数 :param stride: 滑动步长, 决定相邻窗口重叠程度 :return: 二维数组, shape (样本数, window_size) samples [] signal_len len(signal) start 0 while start window_size signal_len: samples.append(signal[start:start window_size]) start stride return np.array(samples)这段代码的逻辑很直白从信号起点开始每次截取window_size个采样点然后向右滑动stride个点继续截取。窗口长度决定模型能看到多长的波形片段步长决定样本数量和重叠率。源码里stride如果小于window_size相邻样本之间就有重叠好处是样本数量多、模型训练更充分坏处是连续样本之间高度相关训练集和测试集如果切自同一条记录就会引入数据泄漏——这是后文避坑章节要重点说的问题。我自己的习惯是把window_size设成1024stride设成512这样一条10万采样点的记录能切出约100个样本。窗口长度不建议小于512因为轴承故障特征尤其是外圈故障的通过频率在时域上需要足够长的观察序列才能稳定出现也不建议超过4096否则单个样本包含太多周期特征被平均化反而降低区分度。2.3 dataset.py标签对齐与训练验证集划分切好的样本要跟故障类别对应上。dataset.py的角色就是读取切片结果和annotations标签文件构建PyTorch Dataset# dataset.py 数据加载与标签映射 import torch from torch.utils.data import Dataset class BearingDataset(Dataset): def __init__(self, samples, labels): :param samples: 预处理后的振动样本, shape (N, seq_len) :param labels: 对应标签, 0Normal, 1Ball, 2InnerRace, 3OuterRace self.samples torch.from_numpy(samples).float() self.labels torch.from_numpy(labels).long() # 1DCNN输入需要(batch, channel, seq_len), channel1 self.samples self.samples.unsqueeze(1) def __len__(self): return len(self.labels) def __getitem__(self, idx): return self.samples[idx], self.labels[idx]注意这段代码里最容易被忽略的一步是unsqueeze(1)。PyTorch的Conv1d期望输入是三维张量batch, channels, length原始振动信号只有一个通道所以要把(N, seq_len)扩展成(N, 1, seq_len)。很多新手在这个维度上翻车报错信息是“Expected 3D input, got 2D”本质上就是忘了加通道维。训练集和验证集的划分源码里一般直接按记录文件名做切分比如3条记录做训练、1条做验证。这种做法的好处是防止同一条记录的滑窗切片同时出现在训练集和验证集里避免模型“记住”而不是“学会”。2.4 标签文件的读取与可视化确认拿到标签文件后我习惯先跑一下visualize.py或者直接用Matplotlib画几条波形确认不同故障类别的时域波形确实存在肉眼可见的差异。CWRU数据里内圈故障和外圈故障在振动幅值和冲击特征上差别明显滚动体故障的冲击周期性较弱画出来一看就能对类别难度有个预判。源码data目录下的数据分析.txt我理解是作者对样本分布做的统计记录包括每类样本数量、每类的标签编号。动手之前看一下这个文件能避免训练到一半发现某个类别只有几十个样本的不均衡问题。3. 1DCNN模型构建CWRUcnn.py的网络设计与核心参数3.1 为什么用一维卷积而不是二维卷积振动信号本质是一维时间序列用1D卷积核沿时间轴滑动直接学习局部波形模式。如果用2DCNN得先把信号做短时傅里叶变换得到时频谱图这一步有两个问题一是STFT的窗函数和窗长选择引入了一个额外的超参数调不好就损失信息二是频谱图丢失了相位信息而轴承故障的冲击特征恰恰和相位强相关。1DCNN把这些都绕开了输入就是原始采样点卷积核在时间维上滑动第一层就能捕捉到故障冲击的局部形态。从计算量上讲1D卷积的参数规模远小于同尺度的2D卷积。一个64长度的1D卷积核输入单通道参数只有64个而同等感受野的2D卷积核至少是64×64。在工业场景下这套模型部署到边缘设备或者嵌入式采集器上时参数量和计算量直接决定能不能实时跑。3.2 CWRUcnn.py的逐层结构拆解models/CWRUcnn.py里定义的网络主体是卷积块堆叠每块包含Conv1d、BatchNorm1d、ReLU和MaxPool1d中间穿插Dropout做正则化最后接全局池化或展平后的全连接层。核心结构如下# models/CWRUcnn.py 一维卷积网络结构 import torch.nn as nn class CWRUCNN(nn.Module): def __init__(self, in_channels1, num_classes4, base_filters32, kernel_size64): super(CWRUCNN, self).__init__() # 第一个卷积块: 捕捉短时冲击特征 self.conv_block1 nn.Sequential( nn.Conv1d(in_channels, base_filters, kernel_sizekernel_size, stride8, paddingkernel_size // 2), nn.BatchNorm1d(base_filters), nn.ReLU(inplaceTrue), nn.MaxPool1d(kernel_size2, stride2) ) # 第二个卷积块: 在更大感受野上提取周期模式 self.conv_block2 nn.Sequential( nn.Conv1d(base_filters, base_filters * 2, kernel_size3, stride1, padding1), nn.BatchNorm1d(base_filters * 2), nn.ReLU(inplaceTrue), nn.MaxPool1d(kernel_size2, stride2) ) # 第三层卷积, 通道数继续翻倍 self.conv_block3 nn.Sequential( nn.Conv1d(base_filters * 2, base_filters * 4, kernel_size3, stride1, padding1), nn.BatchNorm1d(base_filters * 4), nn.ReLU(inplaceTrue), nn.AdaptiveAvgPool1d(1) # 全局平均池化, 输出(batch, 128, 1) ) # 分类头 self.classifier nn.Sequential( nn.Flatten(), nn.Dropout(p0.5), nn.Linear(base_filters * 4, num_classes) ) def forward(self, x): x self.conv_block1(x) x self.conv_block2(x) x self.conv_block3(x) return self.classifier(x)逐层说明一下设计意图。第一层卷积核用了64这么宽的尺寸因为原始波形前几个采样点就能体现出冲击特征但单个采样点噪声太大64长度的卷积核相当于先做了一段短时平滑把局部冲击形态提取出来。stride设成8是为了在浅层就压缩序列长度1024个采样点经过第一层后变成128左右后续层计算量就可控了。后面的卷积块kernel_size都是3通道数逐层翻倍这是典型的通道升维、分辨率降维思路。最后用AdaptiveAvgPool1d(1)代替Flatten直接接全连接好处是网络对输入长度不完全敏感同时大幅减少全连接层参数量。Dropout0.5放在分类头之前是防止最后一个卷积层的特征过拟合。3.3 参数量、感受野与过拟合的平衡这套网络在1024输入长度下参数量大约在百万级别对CWRU这种几千样本规模的数据集来说不算大。训练中如果发现验证集准确率不再提升而训练集还在涨优先检查是不是Dropout没加够、或者卷积层通道数设得太大。源码里还有一个models/BasicModule.py我理解是封装了模型保存和加载的基类训练过程中的checkpoint管理和best model保存都在这个基类里做新加网络结构时继承它就能复用保存逻辑。4. 训练与评估main.py和test.py的参数设置与结果解读4.1 config.py的关键参数表config.py集中管理了训练相关的超参数。我把它读了一遍核心参数整理如下参数名常见取值作用batch_size64 / 128批次大小影响显存占用和梯度稳定性learning_rate0.001Adam优化器的初始学习率epochs50 / 100最大迭代轮数配合早停使用num_classes4 / 10分类头输出维度对应annotations选择optimizerAdam首选自适应学习率收敛稳lossCrossEntropyLoss多分类标准损失devicecuda / cpu指定训练设备seed42随机种子保证实验可复现Adam配0.001初始学习率是这类任务最稳的组合。SGD在这套源码上不是不能用但需要手动调动量和学习率衰减训练时间会明显拉长。loss用CrossEntropyLoss内部已经包含了Softmax计算所以分类头不需要额外加Softmax层。4.2 main.py训练循环的完整流程main.py是训练入口。执行顺序大致是加载config配置创建数据集和数据加载器初始化模型定义优化器和损失函数进入训练循环在每个epoch结束后用验证集评估保存最优模型。# main.py 训练循环核心 import torch import torch.nn as nn from torch.utils.data import DataLoader # 设备选择 device torch.device(cuda if torch.cuda.is_available() else cpu) model CWRUCNN(num_classesconfig.num_classes).to(device) # 优化器与损失函数 optimizer torch.optim.Adam(model.parameters(), lrconfig.learning_rate) criterion nn.CrossEntropyLoss() # 数据加载 train_loader DataLoader(train_dataset, batch_sizeconfig.batch_size, shuffleTrue, num_workers0) val_loader DataLoader(val_dataset, batch_sizeconfig.batch_size, shuffleFalse, num_workers0) # 训练循环 best_acc 0.0 for epoch in range(config.epochs): model.train() running_loss 0.0 for inputs, labels in train_loader: inputs, labels inputs.to(device), labels.to(device) optimizer.zero_grad() outputs model(inputs) loss criterion(outputs, labels) loss.backward() optimizer.step() running_loss loss.item() * inputs.size(0) # 验证 model.eval() correct, total 0, 0 with torch.no_grad(): for inputs, labels in val_loader: inputs, labels inputs.to(device), labels.to(device) outputs model(inputs) _, predicted torch.max(outputs, 1) total labels.size(0) correct (predicted labels).sum().item() val_acc correct / total if val_acc best_acc: best_acc val_acc torch.save(model.state_dict(), best_model.pth)几个细节值得说。model.train()和model.eval()的切换容易漏Dropout和BatchNorm在两种模式下行为完全不同验证时不切回eval模式测试结果会明显偏低。torch.no_grad()在验证阶段一定要加否则会把中间变量保留在计算图里显存越跑越满。训练过程中每轮打印一下训练损失和验证准确率就能看到准确率大概在第几轮趋于平稳。CWRU的4分类任务通常20到30轮就能到95%以上10分类任务因为类别更细收敛会慢一些可能需要50轮以上。4.3 test.py与混淆矩阵结果解读训练完成后test.py负责加载最优模型在测试集上跑完整评估。跟训练时的验证不同test.py会输出全类别的混淆矩阵并保存成results/confuse_matrix_rate.xlsx。这个Excel文件里能看到每个类别的准确率、召回率以及每一对类别之间的混淆情况。轴承故障诊断场景下最怕的是把外圈故障误判成内圈故障这两类故障的冲击特征在时域上有相似性。拿到混淆矩阵后我会先看对角线之外的混叠项如果某两类的混淆率超过5%说明网络对这一对故障的区分特征学习得不够接下来回到数据预处理阶段检查是否窗口长度太长、或者把这两类的样本单独画波形对比。测试脚本里通常还会计算总体准确率和F1分数源码的评估逻辑用一套就够。5. 避坑数据泄漏、随机种子与复现性问题的五个现场5.1 测试集准确率99%换新数据直接崩数据泄漏元凶现象训练时验证集准确率高达99%模型拿出去测新的轴承数据准确率直接掉到70%以下。原因这是这类源码最容易踩的坑。滑窗切片时如果训练集和测试集切自同一条原始振动记录或者切完窗之后才随机打乱再划分同一个故障的连续片段会同时出现在训练集和测试集里。模型看到的测试样本和训练样本高度重叠等于变相背题。解决按原始记录文件而不是按单条样本划分数据集。每一条完整的振动记录只能出现在一个集合里先按记录ID分好train/val/test再在记录内部做滑窗切片。源码里如果data_preprocess.py把切样和打乱放在同一步我会把划分逻辑挪到按记录做。5.2 验证集准确率忽高忽低低得离谱归一化算错位置现象训练集损失正常下降但验证集准确率波动极大甚至远低于训练集。原因特征归一化z-score或者min-max如果对整个数据集先算均值和方差再切分训练集和验证集验证集的信息就泄漏进了训练过程。更常见的情况是归一化用了全量统计量或者压根没对验证集做归一化导致两个集合的数据分布对不上。解决只从训练数据计算均值和方差保存下来验证集和测试集复用同一组统计量。源码里如果归一化写在数据预处理最前面我会改成在dataset.py里按“先拟合并保存scaler再分别Transform”的流程处理。5.3 GPU与CPU上结果不一致复现总是差一点现象同一套代码在GPU上跑两次准确率有0.5到1个百分点的波动换到CPU上结果差得更多。原因PyTorch在GPU上默认使用CuDNNCuDNN的卷积算法是非确定性的不同硬件和驱动版本下卷积计算结果微小不同。此外随机种子虽然设置了但如果没设置CUDNN的deterministic标志数据加载的随机顺序和卷积实现的随机性都会带来差异。解决固定种子还不够需要在main.py开头显式设置torch.backends.cudnn.deterministic True同时把use_deterministic_algorithms打开。代价是训练速度会慢一些但实验可复现更重要。注意PyTorch版本不同这个设置的位置和名字可能有差异代码里如果注释了相关配置优先看注释。5.4 10分类时某类准确率拖后腿类别不均衡现象4分类任务一切正常切到10分类模式某些故障直径的类别准确率只有80%左右其他类别接近满分。原因CWRU不同故障位置和直径组合的样本量天然不均衡正常状态样本占比高某些小故障直径样本少。滑窗切片后样本量少的类别吃到更少的梯度更新模型偏向多数类。解决训练时给损失函数加类别权重或者在数据加载器里做WeightedRandomSampler。类别权重可以直接按样本数量的倒数归一化算出来CrossEntropyLoss的weight参数传入即可。源码config.py里如果没有现成的权重配置加上一个class_weight列表传进去就行。5.5 训练到一半loss直接变成nan学习率与数据范围问题现象前几个epoch正常某个epoch开始loss突然变成nan之后训练崩溃。原因振动数据里偶发的大幅冲击峰值数值范围可能在几百甚至几千原始数据不做归一化直接喂给网络梯度爆炸的风险很高。学习率设得偏大也会加速这个崩盘过程。解决首选把输入信号做标准化确保每个样本的均值为0、方差为1。其次把学习率降到0.0005或0.0003试试。如果还是一样检查BatchNorm在推理时的running_mean是否异常。源码t-SNE和可视化脚本里的数据分布图能辅助确认这一点训练前先画一下输入样本的数值范围大于10倍标准差就要考虑截断异常冲击值并且把学习率降下来这是很多亲手跑这套源码的人的血泪经验。6. 进阶t-SNE特征可视化与重叠滑窗投票6.1 用t-SNE.py验证模型学到了什么t-SNE.py的作用是提取网络倒数第二层全连接层之前的特征把高维特征投影到二维平面可视化看不同故障类别的聚类情况。操作方法不复杂先把模型切到eval状态丢掉分类头用全连接层之前的输出作为特征向量然后调用sklearn的TSNE降维再画散点图。如果网络训练得好同一类故障的样本点会聚成一团不同类别的团之间有明显间距。我拿到手之后先跑了这个脚本出来的图里4分类的四个簇边界清晰10分类的模式略有交叠集中在故障直径较小的两类之间。这个结果说明模型特征提取能力到位、数据预处理标签对齐无误。如果某个类别的点散落在其他类别的簇里回去排查对应类别的样本量是否太少或者标注是否串位。t-SNE图也能顺便验证归一化是否做对正常的特征图是几个紧凑的球拖尾或者散点特别碎往往是数据预处理那里出了问题。6.2 把单样本预测改造成重叠滑窗投票提升在线诊断稳定性训练的模型拿来做实时诊断时直接对一条振动信号切一个窗口做一次预测结果容易抖动。我的习惯是复用一个重叠滑窗投票的trick从连续信号里切多个窗口每个窗口独立预测最后对预测类别做多数表决。具体做法是窗口长度1024步长256连续切9个窗口9次预测中得票最多的类别作为最终结果。这个技巧能明显抑制单窗口内的噪声干扰。单个窗口如果恰好落在冲击盲区模型可能给出错误判断但9个窗口覆盖了大约4096个采样点多数情况下故障冲击至少被几个窗口完整捕获。实际测试里这个做法能把原本单窗口约85%的稳定率拉到96%以上。代价是每次诊断要跑多次前向推理对部署设备的算力有要求但轴承监测通常是周期性诊断间隔几秒一次完全来得及。从那以后我每次跑这类一维卷积诊断源码都会在拿到最优模型之后先做一次特征可视化确认再讨论部署方案基本没再被“测试集漂亮、现场翻车”坑过。希望这份拆解能帮你把这套源码真正跑通在数据预处理和复现这两个最容易栽跟头的地方少走几步弯路。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑