资讯动态

CWRU轴承数据集时频分析实战:STFT/CWT参数与特征提取避坑指南

发布时间:2026/10/17 15:41:47 来源:尧图企业网站定制
简介凯斯西储大学CWRU轴承故障数据集的时频分析文档面向机械故障诊断、设备健康监测方向的初学者与研究者系统讲解如何利用短时傅里叶变换STFT与连续小波变换CWT识别滚动轴承的正常、内圈、滚珠和外圈故障信号。资源为单个docx文档共1个文件压缩包约1.05MB其中包含数据集实验台构成、驱动端/风扇端/基座三类振动数据特点、STFT不同尺度16/32/64与CWT不同小波函数morl、cmor1.5-2、cgau8的对比过程和参数选择结论并附有完整Python代码片段可直接复现时频图。目前已有1582人学习下载。通过这份笔记读者可快速掌握时频分析的原理、操作流程与参数调优思路并基于CWRU公开数据搭建自己的故障识别实验。1. 为什么CWRU轴承故障数据集绕不开时频分析非平稳信号的必然选择凯斯西储大学的轴承故障数据集业内通常直接叫CWRU数据集几乎是旋转机械故障诊断领域最常用、也是最适合用来验证信号处理算法的公开数据它涵盖正常、内圈故障、外圈故障和滚动体故障四种状态每种状态又有不同故障直径和不同负载工况样本量大、信号格式规整。但很多人拿到数据后第一反应是直接做FFT看频谱结果发现内圈0.007英寸和外圈0.007英寸的频谱长得几乎一样分类器训出来换了工况就翻车。原因是轴承振动信号在本质上是非平稳的——滚动体经过故障点时会激发周期性冲击冲击又耦合到结构共振频谱上表现为调制边带而非干净的单根谱线。单靠FFT这种全局变换会把这些时间上的瞬态信息抹平到整个频带里特征自然分不开。把时间信息和频率信息同时呈现出来就是时频分析要做的事。这篇文章沿着一条完整落地路径来讲先讲CWRU数据集怎么读取和划分才不踩数据泄露的坑然后对比两种最常用的时频变换——短时傅里叶变换STFT和连续小波变换CWT的参数设置接着讲如何从时频图里提取出能送入机器学习或深度学习的特征最后给出五个实验中最容易翻车的细节和一套用故障特征频率快速验证时频特征是否有效的脚本。适合正在做故障诊断课题的学生、刚接触CWRU数据的算法工程师以及想把手里的实测轴承信号套进这个流程的现场工程师。2. CWRU数据集的加载与预处理从MAT文件到干净样本的三个关键操作CWRU数据集的落地第一步不是写模型而是把MAT文件读进来之后你的每个操作都会影响后面时频分析的结果。这一章先讲清楚数据集结构再给出可复用的加载和切片代码最后重点说一个很多人忽视的划分陷阱。2.1 数据集结构与文件名编码规则先读懂故障型号再动手CWRU数据是用加速度传感器在实验台架上采集的主要包括驱动端DE、风扇端FE和基座BA三个通道采样频率分12kHz和48kHz两种。文件名的编码规则比想象中更重要内圈故障通常以“IR”开头后面跟故障直径如007代表0.007英寸约0.18mm再接负载值外圈故障是“OR”开头中间还会标出故障点位置比如6点钟方向滚动体故障是“B”开头。文件名的这些信息决定了你加载后打的标签。读取之前我一般会先列一下目录把每一类文件的负载和故障尺寸整理清楚这一步看似枯燥但能省掉后面大量对不上的时间。常见做法是建一个文件清单表把文件名、通道、采样率、故障类型、故障直径、负载六列字段以表格或字典形式记下来再写脚本按这个清单批量加载。CWRU数据里每个.mat文件内部是多个字典键不同版本的数据集键名不完全一致最稳妥的习惯是加载后用keys()看一眼再取值而不是直接假设键名一定叫某个固定名称。2.2 用SciPy读取MAT文件并完成去直流与定长切片下面的代码把单个.mat文件读取成定长的信号样本并完成去直流操作import scipy.io as sio import numpy as np def load_cwru_samples(filepath, channelDE, sample_len2048): mat sio.loadmat(filepath) # 用keys()确认通道键名常见的键是DE、FE、BA print(mat.keys()) signal mat[channel].flatten().astype(np.float64) # 去直流消除加速度计零偏避免0Hz处的直流泄漏 signal signal - np.mean(signal) # 按固定长度切分成多个样本样本之间无重叠 n_samples len(signal) // sample_len samples signal[:n_samples * sample_len].reshape(n_samples, sample_len) return samples这里去直流是必须的一步。加速度传感器输出的信号通常带一个直流偏置不去掉的话做STFT时0Hz附近会出现一条很宽的泄漏谱带会把低频故障特征盖住。定长切片成2048点在12kHz采样率下对应约170毫秒大约包含5个转轴旋转周期足够覆盖轴承故障冲击的周期性重复结构如果切成512点时间上只有约42毫秒转频附近的边带信息会被截断窄带特征很容易丢。注意loadmat返回的字典里键类型是字符串取出信号后建议立刻做类型转换和降维。CWRU数据的DE通道是单列向量但有些版本存入的是二维矩阵flatten()会直接避免维度问题。切片时选择无重叠还是75%重叠取决于样本量需求无重叠生成样本数少但独立性更强重叠采样能成倍扩大数据集但会让相邻样本高度相关训练时如果不能正确分组就会诱发数据泄露。2.3 数据集划分的隐藏雷区按文件组划分而非随机打散这是CWRU实验里最隐蔽的坑。很多人把每个文件切出的几千个样本直接用train_test_split随机打散训练精度很高测试精度也很高但模型一拿到其他工况的数据就崩。原因很简单同一个.mat文件连续切出来的样本在时间上是相邻的噪声和幅值分布几乎一样随机打散时训练集和测试集共享了同一条信号的底层噪声特征等于模型背下了答案。正确做法是保证同一个.mat文件切出的所有样本落在同一侧from sklearn.model_selection import GroupShuffleSplit # 为每个样本打上所属文件的组标签 def assign_group_ids(samples_per_file): group_ids [] for file_idx, count in enumerate(samples_per_file): group_ids.extend([file_idx] * count) return np.array(group_ids) groups assign_group_ids([300, 300, 300]) X np.random.randn(900, 2048) # 示例数据实际替换为真实信号 y np.array([0]*300 [1]*300 [2]*300) splitter GroupShuffleSplit(n_splits1, test_size0.3, random_state42) train_idx, test_idx next(splitter.split(X, y, groupsgroups))GroupShuffleSplit按组划分同一.mat文件的所有切片只会出现在训练集或测试集之一。对于跨负载泛化验证更严格的做法是用某个负载做测试用另外几个负载做训练直接文件级隔离。如果只是做特征提取研究不训练分类器仍然建议按文件分组做可视化否则画的时频图统计结果会被单一文件的噪声特征带偏。3. STFT与CWT的实战参数选择窗长、小波基与分辨率权衡时频变换不是套个函数就完事参数选错后面的特征全建立在错误图像上。这一章给出两个最常用变换的参数设置思路和可直接运行的代码并说明在CWRU数据上应该优先选哪一个。3.1 短时傅里叶变换窗函数、窗长与重叠率的三元组STFT的实质是把信号切成短段再做FFT所以三个参数决定一切窗函数决定频谱泄漏水平窗长决定时间和频率分辨率重叠率决定时间轴的平滑程度。用SciPy实现的典型代码是这样的from scipy.signal import stft import numpy as np fs 12000 # CWRU 12kHz采样 nperseg 512 # 每个窗内样本数 noverlap 384 # 75%重叠 window hann f, t, Zxx stft(signal, fsfs, windowwindow, npersegnperseg, noverlapnoverlap) # Zxx是复数矩阵shape(freq_bins, time_bins) power np.abs(Zxx) ** 2 # 功率谱密度频率分辨率由fs/nperseg决定512点窗对应约23.4Hz的分辨率时间分辨率等于窗长对应的秒数512点约42毫秒。在CWRU近稳态信号上故障特征频率在100Hz到300Hz一带23.4Hz分辨率能分辨出边带结构但如果要精确区分内圈故障和外圈故障的调制边带间隔通常等于转频约30Hz这个分辨率略显不足可以把nperseg提到1024频率分辨率变到11.7Hz时间分辨率变成85毫秒。稳态工况下时间分辨率没那么重要所以我把窗长取到512或1024而不是用很多教程默认的256。窗函数方面汉宁窗是通用选择主瓣宽度适中、旁瓣衰减较快。矩形窗虽然分辨率最高但频谱泄漏严重故障冲击这种宽带信号会让谱线污染一片频带不建议用。重叠率选75%是常规值它让相邻窗之间的信息冗余增大时频图更平滑、能量分布更连续计算量也还能接受。3.2 连续小波变换小波基与尺度序列的匹配逻辑CWT用可变宽度的窗遍历信号低频用长窗获得高频率分辨率高频用短窗获得高时间分辨率这一点比STFT更贴合轴承冲击信号的特点。实现时用PyWavelets里的cwt函数import pywt import numpy as np fs 12000 scales np.arange(2, 128) coefficients, frequencies pywt.cwt( signal, scales, waveletcmor1.5-1.0, sampling_period1/fs ) # coefficients的shape(len(scales), len(signal)) # frequencies返回每个尺度对应的实际中心频率小波基选择直接影响结果。我一般首选复数Morlet波cmor1.5-1.0前面的1.5是带宽参数后面的1.0是中心频率。复小波能同时保留幅值和相位信息对调制边带敏感适合分析故障冲击激发的共振响应。墨西哥帽小波mexh是实值小波计算更快但频率选择性差分析结果比较糊只适合快速预览。尺度序列不是随意填的scales从2开始而不是从1是因为尺度1在数值上接近奈奎斯特频率小波会极度压缩到几个采样点计算出的系数没有物理意义。实际频率与尺度的换算关系是f fc / (scale * dt)其中fc是小波中心频率。cmor1.5-1.0的fc1.0dt1/12000所以scale2对应6000Hzscale128对应约93.75Hz。如果你想重点看100Hz到1000Hz的故障频带就应该把scales按这个范围反推出来而不是套用默认。这个换算逻辑在5.3节会展开讲它就是很多人CWT图“看不清”的直接原因。3.3 两种方法在CWRU数据上的频带表现对比在CWRU这种转速基本恒定的数据上STFT和CWT各有适用范围。我做了很多次对比实验后的习惯是做分类特征时优先用STFT因为它的频率轴是均匀的特征维度稳定、计算快、可复现性好做故障机理分析和冲击定位时用CWT因为它能更清楚地把冲击在时间上的位置和频率上的共振峰同时呈现出来。下面这个对比表汇总了两者的差异维度STFTCWT频率分辨率恒定由窗长决定随频率变化低频更精细时间分辨率恒定由窗长决定高频更精细对冲击信号的敏感度中窗内多个冲击会叠加高瞬时冲击更突出特征维度稳定性固定频率轴适合批量特征尺度轴非线性需统一插值计算开销低中高CWRU稳态场景推荐参数直观适合机理分析工程上还常见一个问题有人把CWT系数直接当图像输给CNN却忽略了不同尺度对应不同频率带宽图像横向和纵向的物理意义并不均匀。相比之下STFT的时频图横轴时间、纵轴频率都是线性均匀的CNN在这些图上学到的卷积核含义更直观。所以我的建议是如果目标是高精度分类从STFT出发如果想发论文讲清故障产生机制再用CWT做补充可视化。4. 从时频图到故障特征的三条提取路径时频分析本身不产出分类结果产出的是高维数据。怎么把一张几百乘几百的时频矩阵压缩成有区分度的特征是这个方向的核心工作。这章给三条从浅到深的路径按成本和效果排序。4.1 边际谱与频带能量比快速量化的第一特征边际谱是时频矩阵沿时间轴累加得到的频谱数学上等于所有时间切片能量之和和传统功率谱类似但来自时频域计算能保留瞬态能量的贡献。它最大的好处是计算极快可以作为任何后续分析的第一步验证# 接上一节STFT得到的f, Zxx psd np.sum(np.abs(Zxx) ** 2, axis1) psd psd / np.sum(psd) # 归一化为概率密度 # 定义关注频带单位Hz bands [(0, 50), (50, 150), (150, 300), (300, 600), (600, 2000)] band_energy [] for lo, hi in bands: mask (f lo) (f hi) band_energy.append(np.sum(psd[mask]))这段代码输出的band_energy向量就是一条最朴素的故障特征。内圈故障的冲击会激发结构共振能量集中在500Hz到2000Hz的高频带外圈故障的冲击传递路径更短高频能量占比有时比内圈更高滚动体故障因为故障点随保持架旋转能量会在调制边带上分散。实际使用时不需要固定成這五段可以先画一次psd曲线看能量集中在哪再反推频带划分。这个特征虽然朴素但和随机森林或SVM配合时在CWRU四分类任务上通常能拿到90%左右的基线精度足够用来验证后续复杂特征是不是真的有用。4.2 时频图像的纹理特征让特征保持空间结构边际谱把时间信息丢了如果故障冲击出现在不同时间段它的差异会被累加抹平。这时直接把时频图当作图像来处理提取纹理特征能保留时间和频率两个维度的空间结构。常用的是局部二值模式LBP和灰度共生矩阵GLCMfrom skimage.feature import local_binary_pattern import numpy as np # 将STFT幅度转为对数刻度并归一化为0-255灰度图 power_db 20 * np.log10(np.abs(Zxx) 1e-12) power_norm ( (power_db - power_db.min()) / (power_db.max() - power_db.min() 1e-12) * 255 ).astype(np.uint8) # LBP纹理特征半径为1的8邻域 lbp local_binary_pattern(power_norm, P8, R1, methoduniform) hist, _ np.histogram(lbp.ravel(), bins10, range(0, 10)) hist hist / hist.sum() # 归一化直方图LBP描述的是每个像素与其邻域的相对大小关系对幅值缩放不敏感正好克服了不同负载下信号幅值差异大的问题。实际使用时P可以取16R取2能得到更多纹理模式但直方图维度会变大需要结合降维。GLCM则统计特定方向上相隔一定距离的像素对出现的频率刻画时频图中的条纹方向——故障冲击会产生竖向条纹共振衰减产生横向扩散这个方向性差异是两类故障的重要可分线索。纹理特征的好处是无需大量训练数据就能稳定描述图像结构缺点是参数多LBP的邻域大小、GLCM的距离和角度都要在验证集上调。4.3 面向CNN的三通道时频图从图像分类借来的思路把时频图直接存成RGB图片再送入CNN是目前故障诊断论文里最常见的做法也是工程上最省事的一条路。关键在于格式统一所有样本必须用相同的采样率、相同的NFFT和重叠率保存图片的尺寸和色彩映射也要一致否则CNN学到的色彩分布和纹理位置就全乱了。import matplotlib.pyplot as plt def save_stft_image(sample, filepath): plt.figure(figsize(6, 4), dpi100) plt.specgram( sample, Fs12000, NFFT256, noverlap192, cmapviridis, scaledB, modepsd ) plt.axis(off) plt.savefig(filepath, bbox_inchestight, pad_inches0) plt.close()specgram内部也是做STFTNFFT256对应的频率分辨率是46.875Hz对纯图像分类来说够用因为CNN更多在学纹理分布而不是精确的谱线位置。保存时关闭坐标轴、去白边能让CNN拿到的输入完全干净。如果走三通道路线可以用三种不同的时频表示各存一张图再拼起来比如STFT幅度图、相位图和CWT尺度图这个做法能提升分类精度但代价是预处理时间翻三倍。我的建议是先跑单通道基线确认时频参数有效后再扩展三通道。5. 时频分析避坑指南CWRU实验中最常见的五个翻车点这一章全是血泪经验。每个问题都是我在实验里真实遇到过的现象按“现象→原因→解决”的顺序写读者可以直接对着自查。5.1 数据泄露跨负载随机划分带来的虚高精度现象用某个负载的数据训完测试准确率98%以上但把模型放到另一个负载的数据上直接掉到70%。有人甚至遇到过训练集和测试集精度都高、单独采一段新数据却完全不可用的情况。原因同一个.mat文件切出的样本高度自相关随机划分时训练集和测试集共享同一段信号的噪声和幅值包络分类器学到的是“这段采集声”而不是故障模式。这也是CWRU实验里最容易被审稿人质疑的点。解决文件级分组划分是第一道锁训练和测试数据必须来自不同的.mat文件。更进一步建议做跨负载验证比如用0hp和1hp训练用2hp和3hp测试这样得到的精度才是模型真正的泛化能力。5.2 内圈与外圈故障的谱线混叠调制边带引发的误判现象画出来内圈故障和外圈故障的时频图目视几乎看不出区别特征向量也很接近分类时这两类老是互相分错。原因CWRU外圈故障在故障点位于承载区时冲击最强传递路径短高频共振明显内圈故障的冲击要经过滚动体、外圈和壳体多级传递能量衰减大但在低频段两者都可能激发类似的调制边带尤其是0.007英寸小故障时信号脆弱、特征微弱。解决不要只看0到2kHz的窄频带把STFT观察范围扩展到4kHz以上在共振频带里做包络谱分析。另一条有效路径是直接用CWT看高频时间切片内圈故障对负载变化更敏感外圈故障相对稳定把这个敏感性差异转化为特征。5.3 小波尺度范围设置不当导致低频成分丢失现象CWT的时频图低频区域一片亮整个画面看起来只有一条宽宽带子故障特征完全被淹没。原因scales设置成np.arange(1, 128)时实际覆盖频率范围是12000Hz到93.75Hz频率轴大部分都落在高频区而轴承故障特征集中在中低频这些频段只占了很少的尺度数量图像自然被高频成分主导。解决用公式f fc / (scale * dt)反推尺度范围。以cmor1.5-1.0为例想看20Hz到2000Hz范围时scale范围约为6到600。实操中先打印frequencies数组确认第一个和最后一个尺度对应的频率再裁剪到目标区间这一步能让CWT图像的信息量发生质变。5.4 12kHz与48kHz采样数据混用频带错位与参数失效现象同一段处理代码在12kHz数据上效果很好换了48kHz数据后特征分布完全变了分类精度骤降或直接报错。原因频率轴物理含义不同导致所有频率相关参数都失效。你以为在看1000Hz处的能量实际上奈奎斯特频率从6000Hz变成了24000HzSTFT的输出频带被拉伸窗长对应的秒数也不同特征向量之间根本没有可比性。解决建立统一实验协议全部使用12kHz的DE通道如果必须用48kHz数据把代码里所有的fs、NFFT、频带边界参数全部按比例调整并重新记录特征含义。时频图保存时统一用物理频率轴标注避免只看像素索引。5.5 归一化放错位置导致时频图质量劣化现象CNN训练时loss不下降或者第一张卷积层的输出几乎全零检查时频图发现有的全黑、有的过曝。原因归一化位置放错了。如果对原始振动信号做零均值单位方差小故障的微弱冲击会被相对放大的背景噪声掩盖如果对全数据集做全局min-max归一化某个通道偶发的偏大会把所有其他样本压到接近0。解决原始信号只去直流不做幅值归一化时频图生成后对每张图单独做归一化让每张图的动态范围都占满0到255。这样既保留了故障冲击的相对强度又让输入图像具有一致的亮度分布。6. 用故障特征频率验证时频特征三行代码快速确认频带差异进入深度学习之前先用理论故障特征频率做一次快速验证能省掉大量无效训练。这一章给出一套可复用的查错流程也是我每个CWRU实验开工前必做的一步。6.1 计算理论故障特征频率轴承参数与转速的换算CWRU实验台使用的是6205型深沟球轴承公开参数是滚动体数9个、滚动体直径约7.94mm、节径约39.04mm、接触角0度。根据这些参数可以推导出内圈故障频率BPFI、外圈故障频率BPFO和滚动体故障频率BSFdef bearing_fault_freqs(rpm): fr rpm / 60.0 n, d, D, alpha 9, 7.94, 39.04, 0.0 cos_a np.cos(np.deg2rad(alpha)) bpfi n * fr / 2 * (1 d / D * cos_a) bpfo n * fr / 2 * (1 - d / D * cos_a) bsf D * fr / (2 * d) * (1 - (d / D * cos_a)**2) return fr, bpfi, bpfo, bsf fr, bpfi, bpfo, bsf bearing_fault_freqs(1797) print(f转频{fr:.2f}Hz, 内圈{BPFI:.2f}Hz, 外圈{BPFO:.2f}Hz, 滚动体{BSF:.2f}Hz)以1797rpm为例转频约29.95HzBPFI约162.2HzBPFO约107.4HzBSF约70.6Hz。这些数值是验证时频图是否保留关键信息的标尺。只要时频参数没设错内圈故障的边际谱应该在160Hz附近出现明显的峰值族外圈故障在107Hz附近存在峰滚动体故障在70Hz和它的整数倍谐波处有能量。如果你的时频图里这些位置静悄悄说明前面的参数设错了不是数据有问题。6.2 验证脚本边际谱峰值与理论值的对应检查下面的函数用10Hz容差检查边际谱在目标特征频率附近是否存在峰值三行代码量级就能完成检查def check_peak_at(psd, f, target_freq, tolerance10): band (f target_freq - tolerance) (f target_freq tolerance) return bool(band.any() and np.max(psd[band]) 0.2 * np.max(psd))逻辑很简单在目标频率±10Hz范围内找边际谱最大值如果这个值大于全频带最大值的20%就认为该特征存在。阈值0.2是经验值可以先从0.1试起逐步提高到能稳定区分内圈和外圈为止。拿这个脚本跑一遍四类数据正常数据在三个特征频率处都不显著内圈故障在BPFI处显著外圈故障在BPFO处显著滚动体故障在BSF处显著才算时频链路搭建正确。这步通过后再去做CNN或者更复杂的特征融合训练过程会顺畅很多。6.3 进阶方向希尔伯特谱与同步压缩变换如果边际谱验证通过但你觉得STFT和CWT的分辨率不够用可以往两个方向进阶。一是希尔伯特-黄变换先把信号做经验模态分解EMD成若干IMF分量再对前几个IMF做Hilbert变换得到瞬时频率对转速波动和幅值调制更敏感。但CWRU稳态数据上EMD容易产生模态混叠端点效应也明显处理不好反而引入伪特征更适合变频调速的实测场景。二是同步压缩变换它是在CWT基础上把系数沿频率方向“挤压”到更精确的瞬时频率位置使时频图上的谱线从宽带变成窄带。在CWRU内圈故障数据上同步压缩能明显把160Hz附近的边带分离得更清楚代价是计算时间大概是CWT的三倍参数也多。我的习惯是先跑通STFT基线再用同步压缩做重点样本的精细分析两者结合既保证效率又保证可靠性。这些方法之间不是替代关系而是验证链上的递进。希望这套从数据读取到特征验证的流程能帮你少走弯路不管你是刚开始碰CWRU数据集还是已经调过一轮参数先停下来用边际谱和特征频率做一次体检总不会错。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑