ARTICLE DETAIL

建站实战干货

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

CWRU轴承数据详解:从文件读取到故障诊断实战全解析

2026/8/29 15:39:30 拓冰建站 浏览量
CWRU轴承数据详解:从文件读取到故障诊断实战全解析 简介在工业设备健康管理与PHM领域轴承故障诊断是核心课题之一而CWRU凯斯西储大学滚动轴承数据集则是该领域公认的基准测试平台。理解振动信号处理的基本原理掌握从原始.mat文件到有效故障特征的完整链路是开展工程实践和算法验证的关键。该数据集涵盖多种故障类型与负载工况通过包络谱分析、特征频率计算以及深度学习模型的构建能够系统评估诊断算法的有效性。无论是进行学术研究还是工业落地评估CWRU数据都为跨工况迁移学习与智能诊断提供了宝贵的实验场景。本文梳理了数据读取、信号切片、特征提取及模型训练中的常见问题与避坑经验帮助工程师与研究者快速建立可复现的故障诊断流程为后续真实工业场景的应用打下坚实基础。 如果你搞过设备健康管理、故障诊断或者PHM方向CWRU凯斯西储大学滚动轴承数据这个数据集大概率绕不开。它基本就是故障诊断圈的MNIST——学术论文用它验证算法工业项目拿它做可行性评估教程里也全是它的影子。不过很多人第一次拿到CWRU数据时的真实反应是一堆.mat文件命名倒是有规律但哪个是内圈故障、哪个是外圈故障、采样率多少、怎么切片、负载怎么选越查越乱。这篇我直接把整套东西拆开讲清楚。从实验台结构、文件命名、采样参数讲起再到Python读取、信号切片、故障特征频率计算最后跑通一个端到端的诊断流程。顺带把我在实际复现中踩过的坑、见过别人踩的坑一次性都列出来。1. 先把CWRU数据集的家底摸清楚1.1 实验台架构一个电机为什么能造出这么多故障数据CWRU轴承数据的采集平台位于凯斯西储大学电气与计算机工程系核心是一台2马力的三相感应电机电机通过联轴器连接一个测功机用来模拟不同的负载工况。在电机驱动端Drive End和风扇端Fan End的轴承座上方分别安装了加速度传感器基座上也有一路加速度信号。实验人员用电火花加工技术在测试轴承上制造单点故障故障直径分为0.007英寸、0.014英寸、0.021英寸、0.028英寸四档然后把故障轴承装进电机启动并记录振动信号。这个实验台结构看起来简单但这种“故障轴承传感器负载调节”的组合很经典。电机驱动端和风扇端各放一个传感器是为了对比不同安装位置对故障信号的影响——驱动端离故障点更近振动冲击更强风扇端信号相对弱但依然包含故障信息。基座信号信噪比最差反倒很适合拿来测试算法在弱信号条件下的表现。理解了这个物理结构后面选择数据通道的时候就不会盲目。另一个值得注意的地方是实验采用的是恒定转速、恒定负载的稳态工况。每一组数据都是在电机达到稳定运行状态后记录的没有启停过程没有负载突变。这对算法调试来说是好事因为干扰因素被严格控制了但这也意味着CWRU数据与现实工业场景有明显差距后面我会专门展开说。1.2 数据文件命名规则看懂文件名就等于看懂了一半CWRU官方提供的数据文件全部是.mat格式文件名由纯数字编号构成例如105.mat、130.mat、3001.mat。很多人第一次进去就懵了光看编号根本不知道对应什么故障。实际规律是官方配套提供了一份数据列表文档通常是Excel里面明确标注了每个编号对应的轴承型号、故障类型、故障直径、负载大小和转速。.mat文件加载后里面通常有这几个变量X_DE_time驱动端加速度信号也是绝大多数研究使用的默认通道X_FE_time风扇端加速度信号常用于对比实验和迁移学习X_BA_time基座加速度信号噪声更大X_RPM电机实际转速部分文件包含这一项故障类型在文件列表里以简写出现IR是内圈故障OR是外圈故障B是滚动体故障也有标Ball的N是正常轴承。外圈故障还会额外标注故障位置比如6点钟方向、3点钟方向、12点钟方向。这个位置信息不是可有可无的它直接影响故障冲击的传递路径和最终诊断效果后面做实验的时候会细说。我给的第一个建议是拿到数据包后先把官方列表下载下来自己整理一份编号到标签的映射字典不要每次临时去翻Excel。这也是后续构建数据集的基础。有些第三方打包好的数据会把文件夹名字改成“IR007_0”、“OR014_1”这种对人更友好但如果用来做实验还是建议回到官方原始文件避免中间环节出问题。1.3 采样参数与实验工况选数据前必须明确的几个数字CWRU数据最常用的采样率是12kHz和48kHz两档。其中12kHz采样的文件覆盖全部故障直径和负载工况数据量适中是绝大多数论文的选择48kHz采样的文件数量少一些但采样点数更多适合需要更高频分辨率的分析。负载共四档0hp、1hp、2hp、3hp。对应电机转速分别约为1797rpm、1772rpm、1750rpm、1730rpm。负载是实验室里的“模拟负载”通过测功机施加并不代表实际工业载荷但这四档工况足够覆盖一个转速变化区间为跨工况算法验证提供了天然场景。负载转速(rpm)转频(Hz)0hp179729.951hp177229.532hp175029.173hp173028.83每段信号时长约10秒12kHz采样率下大约12万个采样点48kHz采样率下大约48万个采样点。也就是说单看一个文件的单通道信号就能切成几十上百个短样本数据总量非常够用。如果你刚开始接触CWRU我建议的默认组合是12kHz采样率、驱动端信号、0hp和1hp负载一起用。这个组合在现有论文里出现频率最高踩坑时最容易找到参考资料。2. 数据读取与第一个信号分析脚本2.1 环境准备用Python读.mat文件CWRU的.mat文件是老版本MATLAB格式不是HDF5格式所以读取非常方便直接用scipy.io.loadmat就能搞定。import numpy as np from scipy.io import loadmat # 以105.mat为例官方文件中它对应0.007英寸内圈故障 mat loadmat(105.mat) print(mat.keys()) de mat[X_DE_time].flatten() # 驱动端信号shape: (121991,) print(de.shape) print(de[:5])这里有一个细节从.mat读出来的数据shape通常是(121991, 1)是个二维列向量。做频谱分析、特征提取前要先flatten()不然很多信号处理函数会报错或者行为异常。还有一个常见坑部分网络重新打包的CWRU数据用了MATLAB 7.3格式HDF5这种情况下loadmat会直接抛错。此时需要用h5py读取import h5py file h5py.File(105_compressed.mat, r) de file[X_DE_time][()].flatten()用h5py读出来的数组需要确认转置和flatten因为HDF5存数组时的维度顺序可能和MATLAB原生格式不一样。不过对官方原版数据用scipy.io.loadmat就够了建议优先用官方原版文件。2.2 信号切片与样本集构建窗口多长、步长取多少拿到一整段连续振动信号后不能直接扔给模型。一般做法是把长序列切成固定长度的短样本每个样本对应一个标签。切多长取决于你要解决什么问题。分类任务里最常见的窗口长度是1024、2048和4096对应12kHz采样率下分别约0.085秒、0.17秒和0.34秒。轴承故障诊断依赖故障冲击的周期性窗口至少要覆盖几个转轴转动周期。以1797rpm为例转频约29.95Hz一个转动周期约0.033秒所以2048点大约覆盖5个转动周期能比较稳定地捕捉到故障特征。我个人通常从2048起步训练样本量和信息量相对平衡。步长方面如果完全不重叠一段12万点的信号能切出约58个样本如果用步长1024样本量能翻倍但相邻样本之间有大量重叠。对于深度学习模型重叠切片可以起到数据增强的作用但测试的时候如果也重叠切片再做随机划分训练集和测试集之间会存在数据泄漏这个问题下面专门说。def sliding_window_slice(signal, window_size2048, stride1024): n len(signal) samples [] for start in range(0, n - window_size 1, stride): samples.append(signal[start:start window_size]) return np.array(samples)切片后的样本通常再做标准化比如减均值除标准差。注意标准化参数只能在训练集上计算测试集要用训练集的参数来变换不能拿整个数据集一起算。2.3 训练集测试集划分的真实误区数据泄漏这是CWRU复现里最容易被忽视、也最容易让结果虚高的问题。我见过不少人在做交叉验证时直接从全部样本里随机抽取20%作为测试集最后准确率刷到99%发文发得也很顺利但换到工业现场数据就立刻崩盘。这种表现本质上是在“记忆”数据而不是“学习”故障模式。数据泄漏的根源在于重叠切片。如果一段连续信号的前面和后面都参与切片且切片间有跳跃重叠那么训练集里某个样本的很大一部分波形可能和测试集里某个样本几乎一模一样。随机划分后这种“孪生样本”极易被模型背下来。我的建议是要么严格不重叠切片样本之间彻底独立要么先按信号段划分比如每段12万点信号前70%点用来切训练样本后30%点用来切测试样本中间留一段空隙。这样即使有重叠来自同一段信号的样本也不会同时落在训练集和测试集里。还有标准化泄漏。很多人用sklearn.preprocessing.StandardScaler对整个数据集做fit_transform然后再划分训练测试集这等于把测试集的均值方差信息提前暴露给了模型。正确流程是先划分再做fit和transform且只fit训练集。3. 故障特征频率计算从裸数据到可解释特征3.1 6205轴承的关键参数与理论公式CWRU实验使用的主测试轴承是SKF 6205-2RS JEM深沟球轴承。它的几何参数完全公开这也是特征频率为什么可以精确计算的原因。关键参数有滚动体数量n9滚动体直径d0.3126英寸节圆直径D1.537英寸接触角约为0度。轴承故障会产生周期性冲击冲击重复频率可以通过几何参数和转频算出来。常见四个特征频率外圈故障特征频率BPFO n/2 × fr × (1 - d/D × cosα)内圈故障特征频率BPFI n/2 × fr × (1 d/D × cosα)滚动体故障特征频率BSF D/(2d) × fr × (1 - (d/D × cosα)^2)保持架故障特征频率FTF 1/2 × fr × (1 - d/D × cosα)其中fr是转频Hz。把6205轴承参数代入接触角α取0可以得到常数系数特征频率系数×fr0hp(1797rpm)下频率(Hz)BPFO3.585理论/ 3.048官方经验值约107 / 约91BPFI5.415约162BSF2.357约71FTF0.398约12这里要注意CWRU官方文档中给出的一些特征频率系数与理论公式计算值存在差异最典型的是外圈官方标注的系数约3.048而纯几何公式算出来是3.585。差异来源主要是实际承载区、滚动体滑移等因素的影响。论文里两种口径都有人用我的做法是分析包络谱时把两个值都画出来观察实际峰值落在哪个频率附近以实测峰值为准不要盲信单一系数。3.2 包络谱实操把故障频率从噪声里找出来包络谱是轴承故障诊断最经典也最有效的分析工具之一。为什么要用包络谱因为轴承故障冲击会激起轴承座或传感器附近的固有高频共振直接看原始信号的FFT故障频率往往被淹没在噪声里。包络谱的思路是先通过带通滤波把高频共振带提取出来再用Hilbert变换求包络信号最后对包络做FFT故障冲击的重复频率就会以明显峰值的形态出现在低频段。import numpy as np from scipy.io import loadmat from scipy.signal import hilbert, butter, filtfilt data loadmat(105.mat) # 0.007英寸内圈故障0hp de data[X_DE_time].flatten() fs 12000 sig de[:3 * fs] # 取前3秒 # 带通滤波中心频率约3000Hz带宽约1000Hz b, a butter(2, [2500, 3500], btypebandpass, fsfs) sig_f filtfilt(b, a, sig) # Hilbert包络 FFT envelope np.abs(hilbert(sig_f)) env_spec np.abs(np.fft.rfft(envelope)) freqs np.fft.rfftfreq(len(envelope), 1 / fs) # 打印前几个峰值对应的频率 top_indices np.argsort(env_spec)[::-1][:5] for i in sorted(top_indices): print(f{freqs[i]:.1f} Hz)对105.mat数据跑完这段代码理论上能看到162Hz附近的峰值也就是BPFI同时还会有它的二倍频、三倍频。如果峰值出现在这个位置说明数据选择正确包络谱流程也跑通了。这是验证整条链路是否正常的最快方法。3.3 不同负载下转频变化对特征频率的影响CWRU的负载档位看似只差1hp但对特征频率的影响很直接。0hp下转频29.95Hz对应内圈故障特征频率约162Hz3hp下转频降到28.83Hz内圈故障特征频率约156Hz。两者差了6Hz左右在分析时如果直接套用0hp的期望频率就可能错过真实峰值。实际操作中我不建议只在一个精确频率点上找峰更合理的方式是设定一个搜索窗口比如期望频率的±5%范围内找局部最大值。如果负载波动较大这个窗口可以放宽到±10Hz。另外还要注意载荷增加会使滚动体产生更多滑移特征频率会有小幅偏移高频倍频处的偏移量会被放大所以看高阶倍频时要格外小心。4. 端到端诊断流程从原始信号到分类准确率4.1 经典机器学习baseline时域统计特征加随机森林直接拿原始波形训练算法也能跑但工程上最稳健的切入点是先做特征工程。特征工程的好处是可解释性强、计算快、对数据量要求低非常适合CWRU这种单通道振动数据。常用的时域统计特征有均值、方差、均方根、峰值因子、波形因子、峭度、偏度等。峭度对故障冲击特别敏感正常轴承的峭度接近3出现局部损伤后峭度会明显升高。再配合频域特征比如频谱质心、主频带功率占比通常就能获得不错的分类效果。def extract_features(x): x np.asarray(x) rms np.sqrt(np.mean(x ** 2)) peak np.max(np.abs(x)) std np.std(x) features [ np.mean(x), std, rms, peak, peak / rms, # 峰值因子 np.mean(np.abs(x)) / rms, # 波形因子 np.mean((x - np.mean(x)) ** 3) / (std ** 3), # 偏度 np.mean((x - np.mean(x)) ** 4) / (std ** 4), # 峭度 ] return np.array(features)特征提取完成后使用随机森林或SVM即可得到很好的baseline。以CWRU的多分类任务正常、内圈、外圈、滚动体故障为例随机森林在这个数据集上拿到95%以上的准确率非常轻松。把特征和标签准备好后用sklearn.model_selection.train_test_split按8:2划分注意设置random_state固定随机种子保证结果可复现。这里我特别强调一下随机种子。CWRU实验数据划分时不同随机种子出来的准确率可能差1到2个百分点。论文实验阶段固定种子能让结果稳定方便对比不同方法的优劣但如果要评估方法的真实水平建议用多个种子跑多次取平均。4.2 深度学习路线1D-CNN直接吃原始波形特征工程虽好但深度学习在故障诊断里已经成为主流。1D-CNN直接以原始振动波形作为输入自动学习特征省去了人工设计特征的步骤。对于CWRU这种样本量充足的场景一个结构简单的1D-CNN就能超过多数传统机器学习方法。以PyTorch为例一个能直接跑的轻量级模型如下import torch.nn as nn class Cnn1d(nn.Module): def __init__(self, num_classes4): super().__init__() self.encoder nn.Sequential( nn.Conv1d(1, 16, kernel_size3, padding1), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(16, 32, kernel_size3, padding1), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.AdaptiveAvgPool1d(1) ) self.classifier nn.Linear(32, num_classes) def forward(self, x): x self.encoder(x) return self.classifier(x.view(x.size(0), -1))输入shape是(batch, 1, 2048)经过两层卷积池化后通过全局平均池化得到32维特征最后接线性分类层。这个模型参数量小在CWRU上训练很快几轮epoch就能收敛到很高的准确率。训练时的几个注意事项batch size建议在32到128之间学习率从0.001开始配合ReduceLROnPlateau或StepLR使用Adam优化器即可建议用Early Stopping防止过拟合。CWRU数据模式相对简单训练集准确率很容易冲到99%关键看测试集的表现以及模型在跨负载、跨工况下是否依然稳定。4.3 评估指标怎么选准确率只是及格线做分类任务大家习惯性地看准确率。CWRU数据因为各类别样本量相对均衡准确率确实能反映一定问题但它不是全部。我建议至少额外看混淆矩阵和每类别的精确率、召回率、F1分数。混淆矩阵能暴露一个典型问题模型是否把某些故障类别混淆了。比如内圈故障和外圈故障有时因为特征相似会被分错如果只看准确率可能察觉不到。再比如滚动体故障的冲击特征不稳定因为滚动体会在运行中旋转故障点不一定每次都撞击到承载区导致这类样本更难分类。这时候单看整体准确率会掩盖滚动体故障召回率偏低的问题。跨负载评估是我觉得CWRU最值得做的实验之一。用0hp数据训练用3hp数据测试看准确率掉多少。这个实验能直接体现模型的泛化能力。很多在单一负载下准确率99%的模型跨负载后可能掉到70%甚至更低。这也是从“拟合数据集”走向“诊断故障”的必经一步。5. 常见问题与避坑实录5.1 mat文件读不了怎么办最典型的表现是loadmat抛出NotImplementedError或者ValueError这通常是文件版本问题。官方原版是旧版MATLAB格式用loadmat直接读如果拿到的是第三方压缩包尤其是用MATLAB 7.3以上保存的就必须换h5py。读取后还要注意键名变化HDF5格式下访问数组时读出来的维度顺序可能和原数据相反建议先打印shape确认一遍再继续处理。另一个小坑是键名不存在。新版SciPy的loadmat会自动过滤掉__header__、__version__、__globals__这些元数据键但不同环境下可能会有差异。稳妥的做法是加载后先执行print(mat.keys())亲眼看看有哪些键再取数不要凭记忆直接写键名。5.2 数据标签对不齐有些同学下载的数据包里文件编号和官方列表对不上或者自己建立文件索引时手滑写错了一个编号导致训练时正常样本混进了故障样本。轻则准确率上不去重则模型完全学错方向却还表现“很好”这种情况最有迷惑性。我习惯在开始实验前写一段代码把计划使用的文件编号、故障类型、故障直径、负载逐条打印出来人工核对一遍。这个动作花不了两分钟但能省掉后续无数排查时间。还有一个不常被提到的问题外圈故障的位置。CWRU的外圈故障数据分6点钟、3点钟、12点钟三个安装位置其中6点钟方向处于承载区故障冲击最强信号特征最明显3点钟和12点钟方向受载荷影响不同特征相对弱。如果只是想做一个标准故障分类通常用6点钟位置的数据就够了但如果想做位置敏感性分析或迁移学习可以刻意混合不同位置的数据。5.3 效果好到离谱CWRU与现实工况的距离这是CWRU数据最大的“坑”。它的数据太干净了恒定转速、恒定负载、单点故障、传感器位置固定、无强噪声污染。在这种条件下很多模型都能拿到99%以上的准确率但这并不能证明模型具备了工业级诊断能力。工业现场有转速波动、负载突变、变工况运行、复合故障、背景噪声、传感器松动等一堆干扰因素模型在CWRU上的表现会明显缩水。所以我的建议是不要把CWRU的准确率当作“我能解决真实工业问题”的证据而是拿它当“算法逻辑是否跑通”的验证工具。做研究可以把CWRU作为基准做落地则需要额外引入更强的对抗性测试比如加噪、变速、跨负载、跨设备验证。5.4 常见问题速查表现象可能原因处理方案loadmat报错文件是MATLAB 7.3格式改用h5py读取检查shape信号全是0或异常值用了错误通道或索引错误打印原始数据统计量核对键名包络谱没有明显峰值带通滤波频带不对换中心频率或用更宽频带跨负载测试准确率暴跌模型过拟合单一转速增加数据增强引入跨域方法训练集测试集准确率差巨大数据泄漏或样本重叠严格按信号段划分避免重叠切片6. 从CWRU往外走迁移学习与工业落地经验6.1 跨负载迁移4档负载是天然的域适应实验场CWRU这个数据集非常适合作迁移学习实验因为天然存在“域”的划分四档负载对应四类转速同一类故障在不同负载下的信号分布有明显差异。经典做法是把某一负载作为源域另一负载作为目标域训练模型时只用源域标签测试时在目标域上评估。比如用0hp数据训练、3hp数据测试可以尝试的迁移方法包括最大均值差异MMD约束特征的深度网络、对抗式域适应DANN、域自适应批量归一化等。这类实验能直观展示特征分布对齐的效果也是把故障诊断研究往真实场景推进的重要一步。但也要清醒认识到CWRU的跨负载迁移难度远低于真实的跨设备迁移。毕竟同一个实验台、同一型号轴承、同样的安装条件只是转速变了。跨设备的域差异通常大得多所以后续追加测试时建议使用其他公开轴承数据集交叉验证比如XJTU-SY滚动轴承加速寿命实验数据集、渥太华大学轴承数据集等。6.2 在这个数据集上还能做的几个方向如果基础分类实验已经做腻了CWRU还有几个衍生方向值得尝试。一个是故障严重程度评估数据本身提供了0.007到0.028英寸四种故障直径可以构建回归模型或有序分类模型从“是否故障”升级到“故障多严重”。另一个是时频图加图像分类模型把一维振动信号转成短时傅里叶变换或小波时频图再用ResNet这类图像模型分类这也是近年论文中的高频组合。还有一个方向是多传感器融合同时使用驱动端和风扇端信号通过双通道网络或注意力机制来利用两个位置的信息在小样本场景下往往比单通道更稳定。6.3 我的一点实操心得我自己现在用CWRU数据的时候已经不太关注准确率还能刷多高了。反而是会刻意把数据弄“脏”给信号加不同信噪比的高斯白噪声、随机切掉部分片段、把训练集和测试集设计成不同负载、甚至把正常样本和故障样本的比例调成不平衡然后观察模型在哪些条件下开始失效。这个过程比单纯刷高准确率有用得多因为真正的工程问题从来不会像干净数据那么简单。最开始上手的时候我也做过那种拿到数据就急着跑模型、最终结果虚高但根本说不清楚学到了什么的事情。后来把一个基本流程老老实实走通——从读mat文件、画波形、看频谱、算特征频率到切片、建模型、跨负载测试——之后才算是真正理解了这套数据。如果你也刚开始接触CWRU建议按这个顺序来先把包络谱跑通确认你能在故障数据里看到理论特征频率再做一版特征工程加SVM的baseline最后再上手深度学习。每一步都跑扎实了后面做实验会顺手很多。本文还有配套的精品资源点击获取