CWRU轴承数据集实战:从数据预处理到故障诊断模型快速搭建

发布时间:2026/9/3 9:53:15
CWRU轴承数据集实战:从数据预处理到故障诊断模型快速搭建 简介本资源是面向机械故障诊断与智能运维领域研究者的凯斯西储大学CWRU轴承数据集完整整理包专为深度学习、信号处理及模式识别初学者与进阶实践者设计有效解决原始CWRU数据分散、格式不统一、标签映射模糊等入门门槛问题。压缩包共172个文件含165个MATLAB格式原始振动信号文件覆盖0.007/0.014/0.021英寸故障尺寸及Ball/InnerRace/OuterRace多位置缺陷、3个核心Python工具脚本含cwru模块封装、2个说明文档含数据结构、采样参数与标签对照表整体大小240.31MB开箱即用。已有1029人学习下载配套代码支持一键加载指定工况如12kHz驱动端、1797RPM、384点截取自动划分训练/测试集并返回标准化特征矩阵、整型标签、16类故障名称映射字典及类别总数显著降低数据预处理成本。1. 项目概述一个工业界的“标准答案”如果你正在研究旋转机械的故障诊断尤其是滚动轴承那么凯斯西储大学CWRU轴承数据集对你来说几乎等同于一个“标准答案”。这个数据集在学术界和工业界被引用了近二十年是验证任何新算法、新模型可靠性的“试金石”。简单来说它提供了一个近乎完美的、可重复的基准测试环境让你能在一个已知的、标注清晰的“战场”上测试你的故障诊断“武器”是否有效。我最初接触这个数据集是为了验证一个基于深度学习的早期故障预警模型。当时市面上能找到的公开数据要么工况单一要么故障类型不全要么数据质量参差不齐很难公平地比较不同算法的优劣。直到发现了CWRU数据集它就像一份精心设计的考卷电机负载从0到3马力可调故障位置内圈、外圈、滚动体和尺寸从0.007英寸到0.021英寸明确采样频率高达12kHz和48kHz确保了信号的丰富细节。这意味着你提出的任何新方法都必须在这套标准考题下证明自己比传统方法比如频谱分析、小波变换更强或者至少不差。然而拿到这个“标准答案”的原始考卷对新手来说并不友好。官网提供的是按实验工况分门别类的.mat文件文件名是诸如97.mat、105.mat这样的数字编码你需要对照一份独立的文档才能知道每个文件对应什么故障。数据读取、预处理、特征提取、数据集划分……每一步都需要自己写代码。这个过程本身就是一个不小的工程很多研究者的第一篇论文可能一半时间都花在了“如何正确使用CWRU数据”上。因此我花时间整理了一套完整的资源包包含原始数据、清洗整理好的结构化数据、以及一套开箱即用的Python程序。这套东西的目的就是帮你跳过繁琐的数据准备阶段直接进入核心的算法研究和模型验证环节。无论你是刚入门的研究生还是需要快速验证想法的工程师这个资源包都能让你在五分钟内跑通第一个实验。2. 数据包深度解析从原始文件到可用特征CWRU数据集的精髓在于其严谨的实验设计。原始数据来源于一个实验台一台2马力的电机驱动端一根扭矩传感器/编码器一个功率测试计以及被测试的轴承。加速度计被安装在电机驱动端和风扇端用以采集振动信号。故障是通过电火花加工技术在轴承的内圈、外圈和滚动体上人工引入的故障直径分为0.007英寸、0.014英寸和0.021英寸三种。2.1 原始数据结构与“解码”官网下载的数据通常是一个压缩包解压后是数十个.mat文件。这些文件命名规则如下正常数据Normal_0.mat,Normal_1.mat,Normal_2.mat,Normal_3.mat分别对应0, 1, 2, 3马力负载下的正常状态。驱动端故障数据这是最常用的部分。文件名如97.mat,105.mat,118.mat等。这里的数字编码需要对照官网的README文档或相关论文。例如97.mat可能代表“驱动端轴承内圈故障故障直径0.007英寸负载0马力”。105.mat可能代表“驱动端轴承滚动体故障故障直径0.014英寸负载1马力”。 每个.mat文件通常包含两个关键变量drive_end驱动端振动信号和fan_end风扇端振动信号以及RPM转速等信息。信号长度通常为120,000个点对应10秒12kHz采样或480,000个点对应10秒48kHz采样。这种编码方式对机器友好但对人极不友好。我的整理工作第一步就是“解码”创建一个映射表将每个神秘的数字文件名转换成人能看懂的标签例如{‘filename’: ‘105.mat’ ‘location’: ‘ball’ ‘fault_size’: 0.014 ‘load’: 1 ‘rpm’: 1772}。2.2 数据预处理与标准化流程原始振动信号是长序列直接扔进模型效果通常不好。我们需要将其转化为模型能更好理解的“特征”。在我的整理程序中标准化流程包含以下几步数据读取与合并使用scipy.io.loadmat读取所有.mat文件根据映射表提取信号和标签构建一个包含所有样本的大列表或字典。信号切片一个10秒长的信号包含数万个点我们可以将其切分成多个更短的样本以增加数据量。例如对于12kHz采样、10秒的信号我们可以用长度为1024的滑动窗口约85毫秒重叠50%切分出200多个小样本。每个小样本都继承原长信号的故障标签。这是时间序列分析中增加样本量的常用技巧。时域特征提取对每一个切片后的信号段计算一组统计特征。这是最基础也最有效的方法之一。我通常提取以下特征有量纲指标均值、方差、均方根值RMS、峰值、峰峰值。无量纲指标峭度Kurtosis、偏度Skewness、波形因子、峰值因子、脉冲因子、裕度因子。 这些特征从不同角度描述了信号的幅值分布和冲击特性。例如峭度对冲击信号非常敏感轴承出现局部故障产生周期性冲击时峭度值会显著升高。频域特征提取对信号进行快速傅里叶变换FFT从频谱中提取特征。频谱重心反映频谱能量集中的位置。频谱方差反映频谱能量的分散程度。特定频带能量根据轴承的故障特征频率通过轴承几何参数和转速计算得出计算内圈、外圈、滚动体故障特征频率附近频带的能量占比。数据标准化不同特征如均值和峭度的数值范围可能相差巨大。为了不让量纲影响模型尤其是基于距离的模型如SVM、KNN需要对特征进行标准化通常使用Z-score标准化减去均值除以标准差使每个特征的均值为0方差为1。经过以上步骤原始的.mat文件就被转化成了一个标准的二维表格特征矩阵和一维向量标签向量可以直接输入到绝大多数机器学习模型中进行训练和测试。注意切片长度和重叠率是需要根据任务调整的超参数。对于早期微弱故障切片太长可能稀释故障特征太短则包含信息不足。通常需要结合故障特征频率的周期来设定。3. 配套Python程序核心模块详解为了让整个过程自动化我编写了一套模块化的Python程序。这套程序不是简单的脚本堆砌而是按照工程化思想组织方便你按需调用和修改。核心模块包括3.1data_loader.py智能数据加载器这个模块的核心任务是“认识”所有数据文件。它内置了文件名到故障类型的映射字典并提供了灵活的加载接口。import scipy.io as sio import numpy as np import pandas as pd from pathlib import Path class CWRULoader: def __init__(self, data_dir): self.data_dir Path(data_dir) # 内置映射关系示例需根据实际文件补充完整 self.fault_map { 97.mat: {location: inner, size: 0.007, load: 0}, 105.mat: {location: ball, size: 0.014, load: 1}, # ... 其他文件映射 Normal_0.mat: {location: normal, size: 0, load: 0} } def load_single_file(self, filename): 加载单个.mat文件返回驱动端信号和标签信息 filepath self.data_dir / filename data sio.loadmat(filepath) # 通常键名为X097_DE_time之类的格式需要探查 for key in data.keys(): if DE_time in key or drive_end in key: signal data[key].flatten() # 确保是一维数组 break else: raise KeyError(f未在文件{filename}中找到驱动端振动信号) label_info self.fault_map.get(filename, {}) return signal, label_info def load_all_to_dataframe(self): 批量加载所有文件并转换为Pandas DataFrame存储特征用 all_features [] all_labels [] for fname in self.data_dir.glob(*.mat): signal, info self.load_single_file(fname.name) # 这里可以调用特征提取函数 features self.extract_time_features(signal) features[label] info[location] features[load] info[load] all_features.append(features) return pd.DataFrame(all_features)这个类的设计让你无需记忆复杂的映射关系通过fault_map字典文件名被自动翻译成有意义的标签。load_all_to_dataframe方法直接将所有数据转化为一个结构化的DataFrame为后续分析提供极大便利。3.2feature_engineer.py一站式特征工厂这个模块封装了从原始信号到特征向量的全过程。它提供了时域、频域等多种特征提取函数并且集成了滑动窗口切片功能。import numpy as np from scipy import stats, fft from scipy.signal import hilbert class FeatureExtractor: staticmethod def sliding_window(signal, window_size, step_size): 将长信号切分为重叠的窗口 num_windows (len(signal) - window_size) // step_size 1 windows [] for i in range(num_windows): start i * step_size end start window_size windows.append(signal[start:end]) return np.array(windows) staticmethod def time_domain_features(signal): 计算时域特征 features {} features[mean] np.mean(signal) features[std] np.std(signal) features[rms] np.sqrt(np.mean(signal**2)) features[peak] np.max(np.abs(signal)) features[peak_to_peak] np.ptp(signal) features[skewness] stats.skew(signal) features[kurtosis] stats.kurtosis(signal) # 波形因子、峰值因子等 features[form_factor] features[rms] / (np.mean(np.abs(signal)) 1e-10) features[peak_factor] features[peak] / (features[rms] 1e-10) return features staticmethod def frequency_domain_features(signal, fs): 计算频域特征 n len(signal) freq fft.rfftfreq(n, d1/fs) amp np.abs(fft.rfft(signal)) # 防止除零 amp_sum np.sum(amp) 1e-10 freq_centroid np.sum(freq * amp) / amp_sum freq_variance np.sum(((freq - freq_centroid)**2) * amp) / amp_sum features {} features[freq_centroid] freq_centroid features[freq_variance] freq_variance # 可以添加更多如特定频带能量比 return features def extract_all(self, signal_window, fs12000): 对一个信号窗口提取全部特征 t_features self.time_domain_features(signal_window) f_features self.frequency_domain_features(signal_window, fs) return {**t_features, **f_features}使用这个类你只需要几行代码就能完成特征工程的核心步骤extractor FeatureExtractor() windows extractor.sliding_window(long_signal, window_size1024, step_size512) feature_list [extractor.extract_all(win, fs12000) for win in windows] feature_df pd.DataFrame(feature_list)3.3model_pipeline.py从数据到评估的完整流水线这个模块将数据加载、特征工程、模型训练、评估和可视化串联起来形成一个完整的流水线。它特别适合快速进行算法对比实验。from sklearn.model_selection import train_test_split from sklearn.preprocessing import StandardScaler, LabelEncoder from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report, confusion_matrix import matplotlib.pyplot as plt import seaborn as sns class FaultDiagnosisPipeline: def __init__(self, loader, extractor): self.loader loader self.extractor extractor self.scaler StandardScaler() self.label_encoder LabelEncoder() self.model None def build_dataset(self, window_size1024, step_size512): 构建特征数据集和标签 all_windows [] all_labels [] # 遍历所有数据文件 for fname in self.loader.data_dir.glob(*.mat): signal, info self.loader.load_single_file(fname.name) windows self.extractor.sliding_window(signal, window_size, step_size) # 为每个窗口提取特征并分配标签 for win in windows: features self.extractor.extract_all(win) all_windows.append(features) all_labels.append(info[location]) # 使用故障位置作为标签 # 转换为DataFrame并编码标签 self.df pd.DataFrame(all_windows) self.df[label] self.label_encoder.fit_transform(all_labels) return self.df def train_evaluate(self, test_size0.3, random_state42): 训练并评估模型 # 准备数据 X self.df.drop(label, axis1).values y self.df[label].values X_train, X_test, y_train, y_test train_test_split(X, y, test_sizetest_size, random_staterandom_state) # 标准化 X_train_scaled self.scaler.fit_transform(X_train) X_test_scaled self.scaler.transform(X_test) # 训练模型这里以随机森林为例 self.model RandomForestClassifier(n_estimators100, random_staterandom_state) self.model.fit(X_train_scaled, y_train) # 预测与评估 y_pred self.model.predict(X_test_scaled) print(classification_report(y_test, y_pred, target_namesself.label_encoder.classes_)) # 绘制混淆矩阵 self.plot_confusion_matrix(y_test, y_pred) return self.model def plot_confusion_matrix(self, y_true, y_pred): cm confusion_matrix(y_true, y_pred) plt.figure(figsize(8,6)) sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabelsself.label_encoder.classes_, yticklabelsself.label_encoder.classes_) plt.ylabel(真实标签) plt.xlabel(预测标签) plt.title(混淆矩阵) plt.tight_layout() plt.show()这个流水线类将整个实验流程标准化。你只需要初始化loader和extractor然后调用build_dataset和train_evaluate就能得到一份完整的模型性能报告和可视化结果。你可以轻松替换其中的模型如换成SVM、神经网络或者调整特征提取函数来对比不同方案的效果。4. 实战指南五分钟快速验证你的第一个诊断模型理论说再多不如亲手跑一遍。下面我们用一个最小化的例子展示如何用整理好的资源包在五分钟内训练一个轴承故障分类模型。步骤1环境准备确保你的Python环境安装了必要的库。你可以使用以下命令快速安装pip install numpy scipy pandas scikit-learn matplotlib seaborn步骤2放置数据与程序将下载的数据包解压假设目录结构如下cwru_project/ ├── data/ │ ├── 97.mat │ ├── 105.mat │ ├── Normal_0.mat │ └── ... (其他.mat文件) ├── cwru_loader.py ├── feature_engineer.py ├── model_pipeline.py └── quick_start.py步骤3编写快速启动脚本创建一个quick_start.py文件内容如下# quick_start.py import sys sys.path.append(.) # 确保能导入当前目录的模块 from cwru_loader import CWRULoader from feature_engineer import FeatureExtractor from model_pipeline import FaultDiagnosisPipeline def main(): # 1. 初始化组件 data_dir ./data # 你的数据文件夹路径 loader CWRULoader(data_dir) extractor FeatureExtractor() # 2. 构建诊断流水线 pipeline FaultDiagnosisPipeline(loader, extractor) # 3. 构建数据集这步可能耗时取决于数据量和窗口大小 print(正在构建特征数据集...) df pipeline.build_dataset(window_size1024, step_size512) print(f数据集构建完成共 {len(df)} 个样本 {len(df.columns)-1} 个特征。) # 4. 训练并评估模型 print(\n开始训练与评估模型...) model pipeline.train_evaluate(test_size0.2) # 5. 可选查看特征重要性如果使用树模型 if hasattr(model, feature_importances_): import pandas as pd feat_importance pd.DataFrame({ feature: df.drop(label, axis1).columns, importance: model.feature_importances_ }).sort_values(importance, ascendingFalse) print(\n特征重要性排序前10:) print(feat_importance.head(10)) if __name__ __main__: main()步骤4运行脚本在终端中运行python quick_start.py如果一切顺利你将看到控制台输出数据集构建信息接着是模型的分类报告精确率、召回率、F1分数以及一张混淆矩阵的热力图。这张图能直观地告诉你模型在哪些故障类型上容易混淆比如把内圈故障误判为滚动体故障。踩坑提示第一次运行时最常见的错误是.mat文件中的变量名与代码中查找的键名不匹配。CWRU数据不同批次、不同来源的文件其内部变量名可能有细微差别。我的CWRULoader类中使用了包含‘DE_time’的查找逻辑如果你的文件里变量名是‘X097_DE_time’就需要调整load_single_file方法中的键名查找规则。一个稳妥的方法是先打印出data.keys()看看里面到底有什么。通过这个快速实验你不仅得到了一个基线模型更重要的是拥有了一个可扩展的实验框架。接下来你可以尝试增加更多频域特征如小波包能量。使用深度学习模型如1D-CNN直接处理原始信号切片。研究不同负载条件下的模型泛化能力。尝试故障尺寸的回归预测而不仅仅是故障类型的分类。CWRU数据集的价值就在于它为这些探索提供了一个坚实、公平的起点。这套整理好的资源包和程序就是帮你快速站上这个起点的“脚手架”。当你熟悉了这套流程完全可以将其迁移到其他类似的振动数据集上你的故障诊断研究之路就从这里真正开始了。本文还有配套的精品资源点击获取