ARTICLE DETAIL

资讯详情

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

基于深度学习的滚动轴承故障诊断毕设实战:CWRU数据与CNN/DNN模型

基于深度学习的滚动轴承故障诊断毕设实战:CWRU数据与CNN/DNN模型 简介这份资源是面向计算机相关专业毕业设计学生与项目实战学习者的深度学习滚动轴承故障诊断完整项目包可直接作为毕设、课程设计或期末大作业使用。项目以CWRU轴承数据集为基础涵盖数据预处理、CNN与DNN模型构建、散点图可视化等典型环节帮助读者理解从原始振动信号到故障分类的完整流程。压缩包共41个文件约34.87MB其中30个mat文件为实验数据4个py脚本负责建模与绘图6个md与1个txt提供说明文档结构清晰、便于按模块查阅。目前已有970人学习下载说明该方案在同类毕设选题中具有较高参考价值。项目经过严格调试下载即用读者可据此快速复现实验、替换数据集或调整网络结构并借助说明文档与脚本注释掌握排错思路为论文撰写与答辩演示提供扎实的代码与数据支撑。1. 拆开这个轴承故障诊断毕设包1750 条 CWRU 数据到底能跑出什么如果你正在做计算机相关专业的毕业设计选题又落在“深度学习 工业信号”这个方向那大概率绕不开滚动轴承故障诊断。这个项目包给的东西很直接一套基于深度学习的滚动轴承故障诊断方法源码外加全部数据主目录叫Fault_Diagnosis主-master里面能看到dnn.py、cnn.py、creat_data.py、pre_data、last_layer_data、plot_scatter.py和一份使用说明。数据侧标注了 CWRU 1750、1730、1772 这几个数字对应凯斯西储大学轴承数据集的样本规模。它解决的不是“从零造轮子”而是让你在有限时间内拿到一条能跑通、能改、能写进论文的实验链路。适合谁做毕设的学生、需要项目实战练习的学习者以及要交课程设计或期末大作业的人。下面我按实际拆包顺序把数据怎么进、模型怎么选、坑在哪讲清楚。2. 数据管线拆解从 CWRU 原始振动信号到 1750 条可训练样本2.1 为什么先看 creat_data.py 而不是直接跑 cnn.py很多人拿到包第一反应是找cnn.py或dnn.py直接python cnn.py然后报错说找不到数据。这是典型的顺序翻车。这个项目的设计逻辑是原始 CWRU 数据先经过creat_data.py做切片和标注生成中间文件再交给pre_data目录下的预处理脚本最后才轮到模型脚本读取。creat_data.py干的事是把连续振动信号按固定窗口切分成样本每个样本带一个故障类别标签。CWRU 数据集本身是按负载和转速分文件的常见做法是用 12kHz 采样下的驱动端数据按 1024 或 2048 点一个窗口切重叠率取 50% 左右。这个包里 1750、1730、1772 这几个数字就是不同类别或不同切分策略下生成的样本量。你如果跳过这一步直接跑模型等于让模型去读空气。2.2 数据切片与标签映射的实操参数下面这段是我按项目结构还原的切片逻辑你可以对照creat_data.py里的实际写法调整。核心是三个参数窗口长度、重叠点数、每类样本上限。import numpy as np import os import scipy.io as sio # 窗口长度1024 点对应 12kHz 采样下约 85ms 的信号片段 WINDOW_SIZE 1024 # 重叠 512 点保证相邻样本之间有 50% 的信息冗余缓解样本不足 STEP 512 # 每类最多取多少个样本防止类别不平衡把模型带偏 MAX_PER_CLASS 400 def slice_signal(signal, window_size, step): 把一维振动信号切成二维样本矩阵 samples [] for start in range(0, len(signal) - window_size, step): samples.append(signal[start:start window_size]) return np.array(samples) def load_cwru_and_label(data_dir): 遍历 CWRU 的 .mat 文件按文件名里的故障代号打标签 all_samples [] all_labels [] # 常见文件名里带 IR内圈、OR外圈、B滚动体、N正常 label_map {N: 0, IR: 1, OR: 2, B: 3} for fname in os.listdir(data_dir): if not fname.endswith(.mat): continue label None for key, val in label_map.items(): if key in fname: label val break if label is None: continue mat sio.loadmat(os.path.join(data_dir, fname)) # CWRU 的驱动端数据通常存在 DE_time 这个键里 key [k for k in mat.keys() if DE_time in k] if not key: continue signal mat[key[0]].flatten() samples slice_signal(signal, WINDOW_SIZE, STEP) if len(samples) MAX_PER_CLASS: samples samples[:MAX_PER_CLASS] all_samples.append(samples) all_labels.extend([label] * len(samples)) return np.vstack(all_samples), np.array(all_labels)逻辑说明slice_signal用滑动窗口把长信号切成定长片段STEP小于WINDOW_SIZE就产生重叠重叠的好处是样本量翻倍坏处是训练集和测试集如果随机划分同一段信号可能同时出现在两边导致准确率虚高。参数说明WINDOW_SIZE改成 2048 会拉长单样本频域分辨率更高但样本总数会减少MAX_PER_CLASS是控制类别平衡的阀门如果某一类原始信号特别长不设上限就会让模型偏向这一类。我一般会先把每类样本数打印出来看一眼再决定要不要截断。2.3 pre_data 和 last_layer_data 的分工pre_data目录通常放的是预处理后的中间文件比如归一化后的 numpy 数组或者 pickle 文件last_layer_data则是模型倒数第二层的特征输出用来做可视化或者迁移学习。plot_scatter.py大概率就是读last_layer_data画 t-SNE 或 PCA 散点图展示不同故障类别的特征分离程度。这个分工很清晰creat_data.py管原始信号到样本pre_data管样本到模型输入last_layer_data管模型中间特征到论文插图。你写论文时如果需要一个“特征可视化”章节直接跑plot_scatter.py就能出图不用自己再搭一套。3. 模型选型与训练dnn.py 和 cnn.py 各自适合什么场景3.1 一维 CNN 处理振动信号的天然优势振动信号是一维时序CNN 的卷积核在一维上滑动能自动提取局部冲击特征。轴承故障的典型表现就是周期性冲击冲击间隔对应故障特征频率一维卷积核刚好能捕捉这种局部模式。cnn.py里常见的结构是几层 Conv1d BatchNorm ReLU MaxPool最后接全连接分类。相比 DNN 把 1024 点直接展平成 1024 维向量CNN 保留了时间结构参数量也更少。我一般会先跑 CNN因为它在 CWRU 这种数据上收敛快准确率也稳。DNN 不是不能用但它更适合做对比实验论文里写“CNN 比 DNN 高 X 个百分点”比只写一个模型更有说服力。3.2 训练脚本的关键参数与代码骨架下面这段是cnn.py的核心训练循环还原重点看学习率、batch size 和早停策略。import torch import torch.nn as nn from torch.utils.data import DataLoader, TensorDataset # 一维 CNN输入通道 1输出类别数按你的标签数改 class BearingCNN(nn.Module): def __init__(self, num_classes4): super().__init__() self.features nn.Sequential( nn.Conv1d(1, 16, kernel_size15, stride1, padding7), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(16, 32, kernel_size7, stride1, padding3), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), ) self.classifier nn.Sequential( nn.Flatten(), nn.Linear(32 * 256, 64), nn.ReLU(), nn.Dropout(0.3), nn.Linear(64, num_classes) ) def forward(self, x): # x 形状: (batch, 1, 1024) x self.features(x) return self.classifier(x) # 训练配置 device torch.device(cuda if torch.cuda.is_available() else cpu) model BearingCNN(num_classes4).to(device) # 学习率 1e-3 是 Adam 在 CWRU 上的常用起点 optimizer torch.optim.Adam(model.parameters(), lr1e-3) criterion nn.CrossEntropyLoss() # batch size 64样本量 1700 左右时一个 epoch 约 27 个 batch loader DataLoader(TensorDataset(X_train, y_train), batch_size64, shuffleTrue) best_acc 0.0 patience 10 wait 0 for epoch in range(100): model.train() for xb, yb in loader: xb, yb xb.to(device), yb.to(device) optimizer.zero_grad() loss criterion(model(xb), yb) loss.backward() optimizer.step() # 每轮在验证集上评估保存最优权重 model.eval() with torch.no_grad(): val_pred model(X_val.to(device)).argmax(dim1) val_acc (val_pred y_val.to(device)).float().mean().item() if val_acc best_acc: best_acc val_acc torch.save(model.state_dict(), best_cnn.pth) wait 0 else: wait 1 if wait patience: print(f早停于 epoch {epoch}最佳验证准确率 {best_acc:.4f}) break逻辑说明卷积层负责提特征全连接层负责分类Dropout 放在全连接前降低过拟合。参数说明kernel_size15对应约 1.25ms 的感受野能覆盖一个冲击周期lr1e-3如果 loss 震荡就降到 5e-4patience10是早停耐心值验证集连续 10 轮不提升就停防止过拟合。注意X_train的形状必须是(样本数, 1, 1024)如果你从creat_data.py拿到的是(样本数, 1024)记得加一维。3.3 DNN 作为对比实验的写法dnn.py通常就是把 1024 点展平后接几层全连接。它的优势是实现简单劣势是参数量大、容易过拟合。论文里放 DNN 的意义在于对比同样的数据CNN 提取局部特征的能力更强准确率通常高 3 到 8 个百分点。你可以在dnn.py里把隐藏层设成 512、256、128加 Dropout 0.5跑出来的结果作为 baseline。如果 DNN 和 CNN 差距很小说明你的数据切分可能有问题比如训练集和测试集重叠了。4. 避坑与排查跑不通、准确率异常、可视化空白怎么查4.1 报错 FileNotFoundError: pre_data 下的 .npy 不存在现象运行cnn.py时提示找不到pre_data里的某个文件。原因creat_data.py还没跑或者跑的时候数据目录路径不对导致中间文件没生成。解决先确认 CWRU 原始.mat文件放在creat_data.py里写的data_dir路径下然后按顺序执行python creat_data.py看到pre_data目录下出现.npy或.pkl文件后再跑模型。如果路径里有中文建议改成全英文Windows 下某些库对中文路径支持不好。4.2 准确率 99% 但换个随机种子就掉到 70%现象第一次跑准确率很高重新划分数据集后准确率暴跌。原因随机划分时同一段信号切出的相邻样本被分到了训练集和测试集模型实际上在“背答案”。解决按原始信号文件划分而不是按切好的样本划分。比如 1750 条样本来自 10 个原始文件那就拿 7 个文件的样本做训练3 个做测试。这样测试集里的信号片段在训练集里完全没出现过准确率才可信。这个坑在毕设答辩时被问到会很致命血泪经验是提前按文件划分。4.3 plot_scatter.py 跑出来一片空白或只有一个点现象执行plot_scatter.py后图像窗口空白或者所有点挤在一起。原因last_layer_data里的特征没有做归一化或者 t-SNE 的 perplexity 参数设得太小。解决先检查last_layer_data的维度如果是(样本数, 特征数)在画图前加一步StandardScaler标准化。t-SNE 的perplexity一般设 30 左右样本少就降到 10。如果还是挤在一起说明模型没学好回去看训练 loss 是不是没降下去。4.4 CUDA out of memory 但显卡显存明明够现象报显存不足但nvidia-smi看显存占用不高。原因PyTorch 缓存了之前的计算图或者 batch size 设太大。解决在训练循环里加torch.cuda.empty_cache()或者把 batch size 从 64 降到 32。另外检查是不是在验证阶段忘了加torch.no_grad()导致验证集也建了计算图显存翻倍。4.5 使用说明.txt 里的命令和实际目录对不上现象按使用说明.txt里的命令跑提示模块不存在。原因说明文档可能是基于作者本地路径写的或者目录层级和你解压后的不一致。解决以实际目录为准用os.getcwd()打印当前路径确认Fault_Diagnosis主-master是不是多了一层嵌套。常见做法是把工作目录切到Fault_Diagnosis主-master下再执行脚本而不是在上一级目录执行。5. 进阶技巧用 last_layer_data 做特征可视化与论文插图最后一章说一个能直接提升论文质量的技巧把last_layer_data用起来。很多人跑完模型只报一个准确率就结束了但毕设论文里如果有特征可视化评审老师会觉得你理解模型内部在干什么。具体做法是在cnn.py里把分类器最后一层之前的输出保存下来每个样本得到一个 64 维或 128 维的特征向量存成.npy文件放到last_layer_data。然后写一个脚本做 t-SNE 降维到二维用不同颜色标不同故障类别。import numpy as np from sklearn.manifold import TSNE import matplotlib.pyplot as plt # 读取模型倒数第二层特征形状 (样本数, 特征维度) features np.load(last_layer_data/features.npy) labels np.load(last_layer_data/labels.npy) # 先标准化避免量纲大的维度主导距离计算 features (features - features.mean(axis0)) / (features.std(axis0) 1e-8) # perplexity 设 30样本少于 200 时降到 10 tsne TSNE(n_components2, perplexity30, random_state42, n_iter1000) embedding tsne.fit_transform(features) plt.figure(figsize(8, 6)) for cls in np.unique(labels): mask labels cls plt.scatter(embedding[mask, 0], embedding[mask, 1], s8, labelfClass {cls}) plt.legend() plt.title(t-SNE of Last-Layer Features) plt.savefig(tsne_bearing.png, dpi300)逻辑说明t-SNE 把高维特征映射到二维类别分得越开说明模型学到的特征判别性越强。参数说明perplexity控制局部和全局的平衡太大则类别混在一起太小则碎片化n_iter1000保证收敛。如果画出来类别重叠严重说明模型还没学好回去调学习率或加数据增强。我一般会在论文里放两张图一张是原始信号的时域波形一张是 t-SNE 特征分布对比说明模型确实学到了东西。从那以后我每次拿到这类毕设包都强制自己先跑通creat_data.py确认pre_data里有东西再动模型脚本。顺序对了后面就顺了。希望帮到你。本文还有配套的精品资源点击获取
返回列表