ARTICLE DETAIL

建站实战干货

来自一线的建站与推广经验沉淀,每一条都经过真实交付验证。

CWRU轴承数据集:从特征工程到深度学习故障诊断全流程实战

2026/8/2 18:59:44 拓冰建站 浏览量
CWRU轴承数据集:从特征工程到深度学习故障诊断全流程实战 1. 项目概述为什么CWRU轴承数据集是故障诊断领域的“教科书”如果你在机械、自动化、故障诊断或者信号处理领域摸爬滚打过一阵子那么“凯斯西储大学轴承数据集”CWRU这个名字大概率会像“MNIST”之于计算机视觉、“Iris”之于机器学习一样成为你绕不开的一个存在。我第一次接触这个数据集还是在研究生阶段做滚动轴承故障诊断课题的时候当时导师直接甩给我一个链接说“把这个数据吃透你的算法验证和论文实验部分就有着落了。” 事实证明这个数据集的价值远超我的预期。简单来说CWRU数据集是一个在实验室环境下系统采集的滚动轴承全生命周期振动信号数据库。它之所以能成为故障诊断领域的“基准测试集”和“入门必修课”核心在于其系统性、公开性和高信噪比。数据集模拟了轴承从健康状态到出现内圈、外圈、滚动体等不同部位、不同尺寸故障的完整过程所有数据均在精密的实验台上获得背景噪声可控故障形态明确。这意味着研究者或工程师拿到数据后无需花费巨大成本搭建实验台就能直接验证自己的故障特征提取算法、智能诊断模型的性能。无论是做传统的时频域分析、小波变换还是现在火热的深度学习比如用一维卷积神经网络处理振动信号CWRU都是首选的“试金石”。对于学生它是绝佳的学习案例对于工程师它是验证算法有效性的可靠依据对于学术界它提供了一个公平比较不同方法的统一平台。2. 数据集核心内容与实验台架解析要真正用好CWRU数据集不能只把它当作一堆“.mat”或“.csv”文件必须理解这些数据是如何产生的背后的物理意义是什么。这就像医生看CT片必须了解扫描设备和人体结构一样。2.1 实验台架数据产生的“母体”CWRU数据采集于一个经典的电机驱动机械故障模拟实验台。这个台架结构清晰是许多高校和实验室的标配理解它有助于你理解数据的“上下文”。实验台的核心是一个2马力的三相感应电机左端通过一根扭矩传感器/编码器连接到右侧的一个功率计上。被测的滚动轴承安装在电机的驱动端风扇端对面或风扇端。为了模拟故障研究人员在轴承上人工加工了单点故障这是关键。故障是通过电火花加工EDM技术在轴承的内圈、外圈或滚动体上刻出直径分别为0.007英寸、0.014英寸和0.021英寸分别约0.18mm、0.36mm、0.53mm的小坑。这种可控的、已知尺寸的故障引入方式使得数据集的标签极其可靠。数据采集使用了加速度计分别安装在电机驱动端壳体12点钟方向和风扇端壳体上采样频率通常为12 kHz或48 kHz不同版本。电机负载通过一个连接到功率计的涡流制动器来调节常见负载为0、1、2、3马力对应约0、746、1492、2237瓦。这个负载变化非常重要因为它模拟了轴承在不同工况下的运行状态你的算法是否能在变负载下稳定识别故障这是一个重要的考核点。2.2 数据文件结构与命名规则下载数据集后你会看到一堆命名似乎有规律的文件例如97.mat(可能代表驱动端0负载7mil故障)105.mat(可能代表风扇端1负载健康状态)130.mat(可能代表驱动端3负载滚动体故障)早期的数据集命名比较隐晦需要对照官方的说明文档通常是一个README或网页来解读。一个典型的命名逻辑是文件编号 轴承位置编码 负载状态编码 故障类型与尺寸编码。例如编号“130”可能被解析为1驱动端33马力负载0特定故障类型如0.021英寸外圈故障。现在CWRU官网和许多整理过的镜像如GitHub上的一些项目提供了更清晰的文件夹结构直接按故障类型、尺寸、负载进行分类例如CWRU/ ├── Normal_Baseline_Data/ # 正常状态数据 ├── 12k_Drive_End_Bearing_Fault_Data/ # 12kHz采样驱动端故障数据 │ ├── 0.007/ │ ├── 0.014/ │ └── 0.021/ └── 48k_Fan_End_Bearing_Fault_Data/ # 48kHz采样风扇端故障数据每个.mat文件通常包含两个关键变量drive_end_vibration和fan_end_vibration或类似名称对应两个加速度计的振动信号以及RPM转速等信息。数据是一维时间序列长度可能为120,000个点对应12kHz采样下10秒的数据或更多。注意务必找到并仔细阅读你所用数据版本的说明文档。不同时期、不同来源整理的数据集结构可能有细微差别错误理解标签会导致整个实验结论失效。3. 数据预处理与特征工程实战要点拿到原始振动信号只是第一步如何将其转化为机器学习或深度学习模型能够“理解”并有效学习的特征是故障诊断成败的关键。这里分享我从传统方法到深度学习方法过渡中的一些核心心得。3.1 传统时频域特征提取打好基础在深度学习普及之前故障诊断严重依赖于专家经验提取的统计特征和频域特征。这些特征至今仍有重要价值特别是对于数据量小或需要模型可解释性的场景。1. 时域统计特征这是最直观的一类特征直接从振动信号的幅值统计中计算得出。常用的包括有量纲指标均值、均方根值RMS反映振动能量、峰值、峰峰值、方差、标准差。无量纲指标峭度Kurtosis对冲击敏感、偏度Skewness波形对称性、波形因子、峰值因子、脉冲因子、裕度因子。import numpy as np import scipy.stats as stats def extract_time_features(signal): 提取时域统计特征 features {} features[mean] np.mean(signal) features[rms] np.sqrt(np.mean(signal**2)) # 均方根值 features[peak] np.max(np.abs(signal)) features[std] np.std(signal) features[kurtosis] stats.kurtosis(signal) # 峭度 features[skewness] stats.skew(signal) # 偏度 # 计算峰值因子峰值 / RMS features[crest_factor] features[peak] / features[rms] if features[rms] ! 0 else 0 return features为什么关注峭度和峰值因子轴承出现局部损伤点蚀、剥落时运行中会产生周期性的冲击脉冲。这些脉冲会使信号分布出现“重尾”峭度增大并且峰值相对于整体能量会显著升高峰值因子增大。因此这两个指标对早期故障非常敏感但同时也容易受到随机噪声干扰。2. 频域特征通过快速傅里叶变换FFT将时域信号转换到频域观察能量在频率轴上的分布。轴承故障有其特征频率计算公式基于轴承几何参数节圆直径、滚子直径、接触角、滚子数量和轴转频RPM/60。内圈故障频率BPFI外圈故障频率BPFO滚动体故障频率BSF保持架故障频率FTF在CWRU数据集中轴承型号如SKF 6205-2RS和电机转速通常为1797 RPM是已知的你可以计算出精确的理论故障频率。然后在频谱图中观察这些频率及其谐波处是否出现明显的幅值升高是判断故障类型的直接证据。3. 时频域分析对于非平稳信号即统计特性随时间变化的信号单纯的FFT不够。常用的有时域同步平均、包络谱分析希尔伯特变换后求频谱对提取冲击特征特别有效、小波变换等。小波变换能同时在时间和频率域提供信号信息非常适合分析振动信号中的瞬态冲击成分。3.2 基于深度学习的端到端特征学习深度学习尤其是一维卷积神经网络1D-CNN改变了游戏规则。它能够自动从原始振动信号或简单的时频图中学习多层次的特征表示省去了复杂的手工特征工程。核心思路将一维振动信号直接作为输入或者先转换为时频图如短时傅里叶变换STFT得到的谱图再作为2D-CNN的输入。一个简单的1D-CNN故障分类模型框架import tensorflow as tf from tensorflow.keras import layers, models def build_1d_cnn(input_length, num_classes): model models.Sequential([ # 第一层卷积捕捉局部模式如冲击脉冲 layers.Conv1D(filters64, kernel_size64, strides2, activationrelu, input_shape(input_length, 1)), layers.BatchNormalization(), layers.MaxPooling1D(pool_size2), # 第二层卷积组合低级特征形成更抽象特征 layers.Conv1D(filters128, kernel_size32, strides2, activationrelu), layers.BatchNormalization(), layers.MaxPooling1D(pool_size2), # 第三层卷积 layers.Conv1D(filters256, kernel_size16, activationrelu), layers.BatchNormalization(), layers.GlobalAveragePooling1D(), # 替代Flatten减少参数对输入长度不敏感 # 全连接层进行分类 layers.Dense(units128, activationrelu), layers.Dropout(0.5), layers.Dense(unitsnum_classes, activationsoftmax) ]) return model实操心得输入标准化至关重要在输入CNN前一定要对每个信号样本进行标准化如减去均值除以标准差否则梯度可能会爆炸或消失导致训练不稳定。数据增强对于振动信号可以在时域进行轻微的时间拉伸、压缩、添加高斯噪声或进行随机切片前提是切片后仍包含完整周期信息这能有效增加数据多样性防止过拟合。使用全局池化层与Flatten层后接全连接层相比GlobalAveragePooling1D层能显著减少模型参数并且对输入信号的长度变化不敏感更具鲁棒性。从简单模型开始不要一开始就堆叠非常深的网络。CWRU数据量相对有限过于复杂的模型极易过拟合。先用一个3-5层的浅层CNN取得基准效果再逐步加深或加宽。4. 基于CWRU数据集的完整诊断流程实现下面我将以一个具体的场景为例展示从数据加载到模型训练评估的完整流程。假设我们的任务是使用驱动端12kHz采样数据区分“健康”、“内圈故障0.021英寸”、“外圈故障0.021英寸”和“滚动体故障0.021英寸”这四类状态电机负载为0马力。4.1 数据准备与划分首先我们需要加载数据并构造适合监督学习的样本和标签。import numpy as np import scipy.io as sio from sklearn.model_selection import train_test_split from sklearn.preprocessing import LabelEncoder, StandardScaler def load_cwru_data(data_path_dict): 加载CWRU数据。 data_path_dict: 字典键为类别名值为对应.mat文件路径列表。 例如{normal: [path/to/normal1.mat, ...], ir_fault: [...], ...} signals [] labels [] sample_length 1024 # 定义每个样本的长度例如1024个点约0.085秒 for label_name, file_paths in data_path_dict.items(): for fp in file_paths: # 加载.mat文件 mat_data sio.loadmat(fp) # 假设振动数据在键‘DE’驱动端下 vibration_signal mat_data[DE].flatten() # 确保是一维数组 # 将长信号分割成固定长度的重叠样本数据增强的一种 num_samples (len(vibration_signal) - sample_length) // (sample_length // 2) 1 for i in range(num_samples): start i * (sample_length // 2) end start sample_length sample vibration_signal[start:end] signals.append(sample) labels.append(label_name) signals np.array(signals) labels np.array(labels) return signals, labels # 假设我们已经将文件按类别整理好 data_paths { normal: [path/to/normal_0.mat], ir_021: [path/to/ir_021_0.mat], or_021: [path/to/or_021_0.mat], ball_021: [path/to/ball_021_0.mat], } X, y load_cwru_data(data_paths) # 编码标签 label_encoder LabelEncoder() y_encoded label_encoder.fit_transform(y) # 划分训练集、验证集、测试集 (60%/20%/20%) X_train, X_temp, y_train, y_temp train_test_split(X, y_encoded, test_size0.4, random_state42, stratifyy_encoded) X_val, X_test, y_val, y_test train_test_split(X_temp, y_temp, test_size0.5, random_state42, stratifyy_temp) # 标准化按训练集的均值和方差标准化所有数据 scaler StandardScaler() # 注意CNN期望输入形状为 (样本数, 时间步长, 通道数)。我们这里通道数为1。 X_train_scaled scaler.fit_transform(X_train).reshape(-1, X_train.shape[1], 1) X_val_scaled scaler.transform(X_val).reshape(-1, X_val.shape[1], 1) X_test_scaled scaler.transform(X_test).reshape(-1, X_test.shape[1], 1)4.2 模型构建、训练与评估使用前面定义的build_1d_cnn模型进行训练。# 构建模型 input_len X_train_scaled.shape[1] num_classes len(np.unique(y_train)) model build_1d_cnn(input_len, num_classes) model.compile(optimizertf.keras.optimizers.Adam(learning_rate0.001), losssparse_categorical_crossentropy, metrics[accuracy]) # 设置回调函数早停和保存最佳模型 callbacks [ tf.keras.callbacks.EarlyStopping(monitorval_loss, patience10, restore_best_weightsTrue), tf.keras.callbacks.ModelCheckpoint(best_cwru_cnn_model.h5, monitorval_accuracy, save_best_onlyTrue) ] # 训练模型 history model.fit(X_train_scaled, y_train, epochs50, batch_size32, validation_data(X_val_scaled, y_val), callbackscallbacks, verbose1) # 在测试集上评估最终模型 test_loss, test_acc model.evaluate(X_test_scaled, y_test, verbose0) print(f测试集准确率: {test_acc:.4f})4.3 结果分析与可视化训练完成后分析模型表现和混淆矩阵了解模型在哪些类别上容易混淆。import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay # 绘制训练历史 plt.figure(figsize(12, 4)) plt.subplot(1, 2, 1) plt.plot(history.history[accuracy], label训练准确率) plt.plot(history.history[val_accuracy], label验证准确率) plt.title(模型准确率) plt.xlabel(Epoch) plt.ylabel(Accuracy) plt.legend() plt.subplot(1, 2, 2) plt.plot(history.history[loss], label训练损失) plt.plot(history.history[val_loss], label验证损失) plt.title(模型损失) plt.xlabel(Epoch) plt.ylabel(Loss) plt.legend() plt.tight_layout() plt.show() # 预测并绘制混淆矩阵 y_pred_probs model.predict(X_test_scaled) y_pred np.argmax(y_pred_probs, axis1) cm confusion_matrix(y_test, y_pred) disp ConfusionMatrixDisplay(confusion_matrixcm, display_labelslabel_encoder.classes_) disp.plot(cmapplt.cm.Blues) plt.title(测试集混淆矩阵) plt.show()通过混淆矩阵你可以清晰看到模型是否将外圈故障误判为健康或者混淆了内圈和滚动体故障。这能指导你后续的模型改进例如增加难分类样本的数据增强或者引入更精细的特征。5. 常见挑战、避坑指南与进阶思路即使使用CWRU这样“干净”的数据集在实际操作中也会遇到各种问题。下面是我和同行们踩过的一些坑以及对应的解决方案。5.1 数据划分的陷阱问题随机划分数据导致“数据泄露”。例如将同一个长信号文件分割出的多个样本随机分到训练集和测试集由于相邻样本高度相似这会让测试结果虚高模型并未学到泛化能力。解决方案按文件或按记录划分。确保来自同一个原始数据文件或同一次实验记录的所有样本要么全在训练集要么全在测试集/验证集。这模拟了现实场景我们用过去某些设备的历史数据训练模型去预测未来或其他设备的数据。5.2 类别不平衡问题问题CWRU数据集中不同故障尺寸7mil, 14mil, 21mil的数据量可能不同或者你在构造多负载联合诊断任务时某些负载下的数据较少。解决方案重采样对样本数少的类别进行过采样如SMOTE算法但需谨慎用于时间序列或对样本数多的类别进行欠采样。类别权重在模型训练时通过class_weight参数给少数类别更高的损失权重让模型更关注它们。数据增强对少数类样本进行更丰富的数据增强如添加不同强度的噪声、进行小幅度的缩放和平移。5.3 模型过拟合问题训练集准确率很高但验证集和测试集准确率很低模型“死记硬背”了训练数据。解决方案简化模型减少网络层数、滤波器数量。增强正则化增加Dropout层比率、在卷积层或全连接层添加L2正则化kernel_regularizer。使用更激进的数据增强。早停Early Stopping监控验证集损失当其不再下降时停止训练。5.4 从实验室到现场的鸿沟问题在CWRU上表现99%的模型用到工厂实际数据上可能一塌糊涂。因为实验室数据信噪比高、工况单一而现场数据噪声大、工况复杂多变。进阶思路域自适应Domain Adaptation研究如何让在CWRU源域上训练的模型能够适应目标现场目标域数据。即使目标域没有标签或只有少量标签。迁移学习将在CWRU大数据集上预训练好的模型尤其是特征提取层用少量现场数据进行微调Fine-tuning。噪声注入训练在训练时主动向CWRU的干净信号中添加不同强度的高斯噪声、工频干扰等提升模型的抗噪能力。多工况融合训练利用CWRU提供的多种负载数据在训练时就让模型学习不同负载下的特征提高其工况鲁棒性。5.5 特征可视化与可解释性问题深度学习模型是“黑箱”我们不知道它根据什么做出了判断。解决方案Grad-CAM梯度加权类激活映射可以大致可视化出输入信号的哪些时间段对模型的决策贡献最大。这有助于我们判断模型是否关注了正确的故障冲击时刻。t-SNE/UMAP降维将模型最后一层卷积或全连接层输出的高维特征降维到2D或3D进行可视化观察不同故障类别的样本在特征空间是否能被清晰分离。这能直观反映模型特征学习的好坏。CWRU数据集是一个宝藏但它只是一个起点。它为你提供了验证想法、学习流程的绝佳沙盒。真正的挑战在于如何将在这个“理想实验室”中锤炼出的方法迁移到充满不确定性的真实工业世界。我的体会是永远对模型在CWRU上的接近满分保持警惕多思考“如果信号变脏了、变慢了、负载突变了我的方法还管用吗” 带着这个问题去改进你的特征工程、模型结构和训练策略才是从“玩具数据集”走向“工业级应用”的关键一步。最后一个小技巧在论文或报告中汇报结果时除了整体准确率务必给出混淆矩阵并详细分析误分类案例这比一个孤零零的99.5%更能体现工作的严谨性和深度。