简介:在工业设备健康管理与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) |
|---|---|---|
| 0hp | 1797 | 29.95 |
| 1hp | 1772 | 29.53 |
| 2hp | 1750 | 29.17 |
| 3hp | 1730 | 28.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_size=2048, stride=1024):
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深沟球轴承。它的几何参数完全公开,这也是特征频率为什么可以精确计算的原因。关键参数有:滚动体数量n=9,滚动体直径d=0.3126英寸,节圆直径D=1.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,可以得到常数系数:
| 特征频率 | 系数(×fr) | 0hp(1797rpm)下频率(Hz) |
|---|---|---|
| BPFO | 3.585(理论)/ 3.048(官方经验值) | 约107 / 约91 |
| BPFI | 5.415 | 约162 |
| BSF | 2.357 | 约71 |
| FTF | 0.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], btype="bandpass", fs=fs)
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,对应内圈故障特征频率约162Hz;3hp下转频降到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_classes=4):
super().__init__()
self.encoder = nn.Sequential(
nn.Conv1d(1, 16, kernel_size=3, padding=1),
nn.BatchNorm1d(16),
nn.ReLU(),
nn.MaxPool1d(2),
nn.Conv1d(16, 32, kernel_size=3, padding=1),
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;最后再上手深度学习。每一步都跑扎实了,后面做实验会顺手很多。
4593




被折叠的 条评论
为什么被折叠?



