
简介面向机械故障诊断初学者与研究者的一份技术文档围绕凯斯西储大学轴承故障数据集展开信号时频分析帮助读者理解振动信号在故障识别中的处理思路与参数选择依据。文档共1个docx文件压缩包约1.05MB篇幅集中、便于查阅内容覆盖实验台构成、驱动端/风扇端/基座三类振动数据的物理含义以及正常、内圈、滚珠、外圈故障信号的对比分析。文中以短时傅里叶变换和连续小波变换为主线讨论窗尺度与时间、频率分辨率的权衡比较不同小波函数及多尺度设置下的时频图表现并给出尺度32的STFT与cmor1.5-2小波的选用理由。已有1582人学习适合希望快速建立时频分析直觉、复现实验思路并用于课程设计或课题预研的读者参考。1. 同一段振动信号换个窗长结论就翻了0.021 英寸的内圈缺陷放在窗长 32 点的短时傅里叶变换图上只是一条贴着底噪的淡影把窗长推到 64冲击边带才勉强露出来。同一份轴承故障数据集、同一段 1024 点切片、同一个采样率只改了窗长这一个参数能看出的东西完全不是一个量级。时频分析翻车大多不是算法写错而是参数选错还照着图下了结论。这篇讲的就是我把短时傅里叶变换和 Morlet 连续小波在这套轴承故障数据集上并排跑了一遍之后怎么定窗长、怎么挑小波、怎么排尺度以及中间踩过的那些坑。刚上手做设备健康监测的人可以照着抄参数做过一阵子的人可以拿我的判断依据对着自己的结论核一遍。2. 选型之前先摸数据三路加速度计决定你该分析哪一列时频分析的第一步不是打开pywt而是搞清楚你手上这份数据的物理来源。这套公开的轴承故障数据集采自一台 1.5 kW2 马力的电机测试台台架上依次是电机、扭矩传感器/译码器、功率测试计另外还有一套没在台架照片里露面的电子控制器。加速度计分别贴在电机壳体的驱动端、风扇端和基座上。同一时刻、同一台设备三个位置记录下来的振动在物理上根本不是一回事选错通道后面的窗长和小波参数调得再细也是白搭。2.1 驱动端、风扇端、基座三路信号各能看出什么驱动端测的是转子旋转和传动系统激励叠加后的振动轴承故障、齿轮啮合异常这类特征在这一路上最干净信噪比也最好所以绝大多数轴承故障识别的公开实验都默认用驱动端数据。风扇端主要受风扇叶片旋转和风扇系统激励影响叶片失衡、风扇侧轴承故障会在这里更明显但它离被测轴承远缺陷冲击传到这一路已经被衰减和调制过一轮。基座测的是整机振动电机不平衡、底座松动这类全局性问题跑不掉可单点轴承的早期缺陷在这里基本被结构噪声盖住。我给的建议很直接做单点轴承缺陷的时频特征对比用驱动端通道验证结论是否只在某一个测点成立再拿另外两路做交叉。这一步的判断依据不是玄学而是传感器的物理位置决定了信号里谁占主导。很多人拿到数据先看文件大小、先跑一遍代码出图图出来了才发现自己用的那一路根本没有目标缺陷的冲击成分返工成本比先花十分钟读数据说明高得多。2.2 四种状态与 0.021 英寸缺陷的取样口径对比实验要有对照这套数据里最省事的组合是四条一条正常基线加上 0.021 英寸的内圈、滚珠、外圈三种缺陷。选同一个缺陷尺寸是为了让变量只剩故障位置不然内圈 0.007 和滚珠 0.021 放一起比你分不清图上的差异是位置造成的还是尺寸造成的。取样口径也要统一。常见的做法是从每一条记录里截取前 1024 个采样点当一段样本四条记录用同样的长度、同样的起点规则。这里有个容易被忽略的细节不同记录的文件名不同对应的通道键名也不同如果代码里把X097_DE_time这种键名写死换一个文件立刻报 KeyError。稳妥的写法是遍历字典的键、按后缀匹配让代码自己去认通道。另外直接从第 0 点截取有可能截到电机启动的瞬态段冲击成分被启动过程污染看到亮条先别高兴先确认这段是不是稳定运行段。对比项取值目的通道驱动端加速度DE缺陷冲击最干净状态正常、内圈、滚珠、外圈位置可区分缺陷尺寸统一 0.021 英寸消除尺寸干扰单段长度1024 点覆盖多个冲击周期采样频率按数据说明标称值填决定频率轴刻度3. STFT 窗长怎么定16、32、64 三档比出来的结论短时傅里叶变换的机制很朴素拿一个窗函数在时间轴上滑动在每一段窗内做傅里叶变换把一维时序变成时间-频率-幅值的三维矩阵。它的全部取舍都压在一个参数上——窗长。窗长定下来时间分辨率和频率分辨率就同时被锁死了这是海森堡不确定性在信号处理里的直接体现没有两全其美的选项只有针对任务的最优解。3.1 时间分辨率与频率分辨率的取舍用什么指标判断窗长小时间轴上切得细能定位冲击发生的具体时刻但每个窗内的采样点太少频率轴上糊成一片内圈故障那种间隔性的冲击边带会连成一条宽带看不出层次。窗长大频率轴上分得细边带之间的间隔能数出来但时间轴被拉平冲击的周期性被抹掉图上只剩一条水平亮线。判断该往哪边偏我一般看两件事。第一目标特征到底是什么时候发生还是频率落在哪。轴承缺陷的冲击重复频率按轴承几何参数和转速算出来的内圈、外圈、滚珠特征频率是关键判据那频率分辨率就更重要窗长往大了给。第二同类故障之间的区分度。四张图放在一起正常、内圈、滚珠、外圈能不能一眼分开分不开就说明参数还没到位。实际比下来16 这一档时间分辨率够用但频率轴太糊三种缺陷的图长得差不多32 这一档两类分辨率都还能接受四种状态的图能拉开差距64 这一档频率细节最清楚但冲击的时间定位开始丢滚珠故障那种间歇性冲击的节拍看不出来了。综合辨识度和两类分辨率的平衡我最终把 STFT 的窗长定在 32重叠率取 0.5。提示重叠率不是越大越好。0.5 意味着步长是窗长的一半再往上加计算量线性涨图只是更平滑判据不会变多。3.2 可复现的 STFT 代码窗长、重叠率、切片长度下面这段是把上面三档参数并排跑出来的最小可复现代码改的是窗长量的是同一段内圈信号图题和参数严格对应——这一点很关键后面避坑章节会专门讲。import numpy as np from scipy.io import loadmat from scipy.signal import stft import matplotlib.pyplot as plt matplotlib.rc(font, familyMicrosoft YaHei) def load_de(path): 按后缀匹配通道键名避免换文件就 KeyError d loadmat(path) key [k for k in d if k.endswith(DE_time)][0] return d[key].reshape(-1) # 四条记录正常 / 0.021 英寸内圈 / 滚珠 / 外圈 sig_n load_de(0_0.mat)[:1024] sig_i load_de(21_1.mat)[:1024] sig_b load_de(21_2.mat)[:1024] sig_o load_de(21_3.mat)[:1024] FS 12000 # 换成你那份数据说明里标称的采样频率 fig, axes plt.subplots(2, 2, figsize(18, 9)) for ax, nper in zip(axes.ravel(), (16, 32, 64, 128)): # nperseg 为窗长noverlap 取半重叠boundaryNone 避免两端补零失真 f, t, Z stft(sig_i, fsFS, windowhann, npersegnper, noverlapnper // 2, boundaryNone, paddedFalse) ax.pcolormesh(t, f, np.abs(Z), shadinggouraud, cmapjet) ax.set_title(f内圈 nperseg{nper}) # 标题跟着参数走不写死 ax.set_ylabel(频率 / Hz) plt.tight_layout() plt.show()关键参数逐个说清楚。nperseg是窗内采样点数也就是大家口中常说的尺度它同时决定频率轴的分辨率和时间轴的步长noverlap取nperseg // 2就是 0.5 重叠滑动步长等于半个窗fs只影响频率轴的刻度标注填错不会报错但会让你把 3 kHz 当成 1.5 kHz 去解读属于最隐蔽的一类错误windowhann用汉宁窗抑制频谱泄漏换成矩形窗会看到明显的旁瓣拖尾boundaryNone, paddedFalse关掉两端补零否则图的两侧会出现一段振幅被强行拉低的假区域误判成故障消失了。3.3 看图三步先看边带、再看周期性、最后看底噪图出来了不等于读懂了。我习惯按固定顺序扫一遍先看目标频率附近有没有边带轴承缺陷的特征频率如果按转速算出来落在某个区间就看那一片的亮度是不是比正常基线高再看时间轴上亮条的重复节拍外圈缺陷的冲击是等间隔的滚珠缺陷会带调制、节拍不均匀最后看底噪水平正常基线那一条如果整体比故障图还亮说明两组数据的量级没对齐先做归一化再比不然你比的是幅值不是特征。这三步做完再回到窗长上做取舍才算有依据。跳过第二步直接看频率很容易把工频及其谐波当成故障特征——那几条横贯全图的亮线是电机转速基频和倍频位置固定、不随时间变化和故障冲击的间歇性完全不同。4. 小波函数怎么挑cgau8、morl、cmor1-1、cmor1.5-2 四个候选逐项对比STFT 的窗长一旦定死整个时频平面的分辨率就是均匀的高频段和低频段一个待遇。连续小波变换换了个思路用可伸缩的小波基函数小尺度对应高频、大尺度对应低频天然是高频时间细、低频频率细的变分辨率结构。代价是多了一个新问题——小波函数本身怎么选。这套数据上某篇故障诊断方向的论文推荐cgau8另外三个常见候选是morl、cmor1-1、cmor1.5-2四个都得跑一遍才有说服力。4.1 带宽、中心频率与尺度序列 cparam 的对应关系先厘清几个概念不然代码里的参数全靠猜。morl是标准 Morlet时频局部化好振动信号和生物医学信号里用得最多。cmor是复数 Morlet命名格式是cmor{B}-{C}B 是带宽参数控制小波在频率域的宽度C 是中心频率控制小波的振荡频率所以cmor1-1是带宽 1、中心频率 1cmor1.5-2是带宽 1.5、中心频率 2。带宽越大频率分辨率越差但时间定位越锐中心频率越高同样的尺度下对应的实际频率越高。cgau是复数高斯小波cgau8里的 8 是阶数阶数越高对高斯型信号逼近越好对冲击型信号的响应会偏钝一些。尺度序列的构造更值得说。pywt.cwt的第二个参数是 scales 数组光看着尺度 128没法知道对应多少赫兹。通用的写法是先取小波的中心频率fc再按cparam 2 * fc * totalscal算常数项最后用cparam / np.arange(totalscal, 0, -1)生成从大到小排列的尺度序列。这个除法把尺度和频率挂上钩尺度越大对应的频率越低。尺度到频率的近似换算是freq ≈ fc / (scale * dt)dt 是采样周期所以尺度翻倍中心频率大致减半。4.2 CWT 代码尺度序列怎么生成四个候选用同一段内圈信号、同一个尺度长度 128 跑一遍控制变量才能比出差异。import numpy as np import pywt import matplotlib.pyplot as plt matplotlib.rc(font, familyMicrosoft YaHei) totalscal 128 # 尺度序列长度决定频率轴的采样密度 names (cgau8, morl, cmor1-1, cmor1.5-2) fig, axes plt.subplots(2, 2, figsize(18, 9)) for ax, name in zip(axes.ravel(), names): fc pywt.central_frequency(name, precision8) # 小波中心频率 cparam 2 * fc * totalscal # 常数项 scales cparam / np.arange(totalscal, 0, -1) # 尺度由大到小 coef, freqs pywt.cwt(sig_i, scales, name, sampling_period1 / FS) ax.contourf(np.arange(len(sig_i)) / FS, freqs, np.abs(coef), levels40, cmapjet) ax.set_title(f内圈 {name}) ax.set_xlabel(时间 / s) ax.set_ylabel(频率 / Hz) plt.tight_layout() plt.show()几个参数得交代。pywt.central_frequency(name, precision8)返回小波基在频域的中心频率是构造尺度序列的前提注释掉它后面必然 NameError——这不是理论问题是我真踩过的。sampling_period1/FS传进去返回的freqs才是真实频率Hz不传就是一个无量纲的相对值纵轴标签只能写相对频率写 kHz 就是错的。新版 PyWavelets 里pywt.cwt的返回值叫frequencies老版本叫freqs跨版本抄代码第一件事就是确认这个。contourf的 x 轴这里用采样点索引除以采样频率生成长度必须和系数矩阵的时间维一致用别的长度会直接抛维度不匹配。4.3 尺度 32、64、128、256 的对比与结论四个小波函数在同一尺度长度下比cgau8和cmor1.5-2对三种故障的区分度明显更好正常基线和故障图的层次能拉开morl的图整体偏糊边带细节少一截cmor1-1居中滚珠故障那一张和正常基线靠得比较近。综合频率和时间两类分辨率的表现我把小波基定在cmor1.5-2。接着用cmor1.5-2单独比尺度长度 32、64、128、256同样用滚珠故障那段数据cparam一律按2 * fc * totalscal生成。结论很稳定尺度长度越大图底部低频区域的信息越丰富低频调制成分的层次越清楚尺度长度越小高频段的瞬态冲击定位越锐但低频几乎被压平成一条。这正好印证小波变换的双尺度性质——盯高频特征用小尺度盯低频特征用大尺度。128 这一档在两类特征之间平衡最好冲击的重复节拍和低频边带同时可读所以最终定 128。小波基带宽中心频率三类缺陷区分度结论cgau8阶数 8由阶数决定较高备选冲击响应偏钝morl11一般细节偏糊不选cmor1-111中等滚珠故障贴近基线cmor1.5-21.52较高最终选用尺度长度3264128256高频冲击定位锐较锐可读偏钝低频调制层次差一般清楚最清楚综合判断不选备选选用只做低频复核5. 避坑与排查五个让我返工的细节这一节全是血泪经验。时频分析的坑不在于算法难而在于图上看着挺像那么回事、结论却是错的而且错得很安静不报错、不告警全靠你自己发现。5.1 图题和实际参数对不上看图的人被自己骗了现象四张子图的标题写着尺度 16 / 32 / 64 / 128但代码里nperseg实际传的是 32 / 64 / 128 / 256图题前半句是手写的常量。原因标题字符串没跟着循环变量走代码改过一轮、标题没同步改。解决标题一律用 f-string 绑定参数变量让图自己说话出图后先扫一眼标题和代码里的值是否一一对应再开始判读。这类错最坑的地方在于它会让你把32 的表现记成16 的表现整个参数结论全歪。5.2 通道键名写死换一个文件就 KeyError现象照着示例代码跑第一个文件正常换第二个文件立刻KeyError: X097_DE_time。原因每条记录内部的变量名不同示例里写死的键名只对那一条记录成立且loadmat返回的是字典不是数组。解决用[k for k in d if k.endswith(DE_time)][0]按后缀匹配或者先print(d.keys())看清结构再取值。顺带说一句取出来的是一维列向量记得.reshape(-1)打平不然后面切片和 STFT 会出现维度告警。5.3 中心频率那一行被注释掉一路错到 NameError现象跑 CWT 对比时第一个小波正常第二个直接报变量未定义。原因fc pywt.central_frequency(name)这一行在某些版本里被注释掉了但下面cparam 2 * fc * totalscal还在用它。解决把中心频率的计算放进循环内部每个小波基各算各的不要图省事提到循环外共用——morl和cmor1.5-2的中心频率根本不是同一个值共用等于给所有小波基套了同一个尺度映射。5.4 版本差异freqs 和 frequencies 换来换去现象从别处抄来的代码pywt.cwt那行报TypeError: unexpected keyword argument或者解包时报too many values to unpack。原因不同版本的 PyWavelets 对返回值和关键字参数命名做过调整老代码里的freqs和新版里的frequencies不是一回事。解决先import pywt; print(pywt.__version__)看版本再对着该版本的接口写不确定就只解包两个返回值然后把第二个值打印出来看量纲判断它是频率还是尺度索引别想当然当赫兹用。5.5 尺度越大越清楚是错觉现象把尺度从 128 拉到 256 甚至更高图底部出现大片明亮区域看起来特征更强了于是把结论往大尺度上调。原因大尺度对应低频而低频段往往叠着工频及其谐波、转频调制、台架结构共振这些成分幅值本来就高一亮就抢眼但它不是缺陷特征。解决先按转速和轴承几何参数把理论特征频率算出来在图上标一条参考线只在参考线附近判断有没有变亮同时永远保留正常基线做对照基线在同一个位置也亮那就不是故障特征。6. 参数表与落地流程我最后固化的那套设置把上面所有对比收拢成一张表就是我最后固化下来的配置。STFT 用汉宁窗、窗长 32 点、0.5 重叠做快速筛查和冲击时刻定位CWT 用cmor1.5-2、尺度长度 128、cparam 2 * fc * totalscal生成尺度序列做精细的时频结构分析。两者不是二选一是同一条流水线上的两道工序。环节参数取值为什么数据通道驱动端 DE缺陷冲击最干净数据单段长度1024 点覆盖多个冲击周期STFT窗长 nperseg32两类分辨率平衡点STFT重叠 noverlap160.5兼顾平滑与算力STFT窗函数hann抑制频谱泄漏CWT小波基cmor1.5-2三类缺陷区分度最好CWT尺度长度128高低频同时可读CWT尺度序列cparam / arange(128,0,-1)尺度与频率挂钩6.1 从数据到结论的五步流程第一步读数据说明确认采样频率和三个测点位置选定驱动端通道统一取前 1024 点、统一用 0.021 英寸这一档缺陷尺寸。第二步先画原始时域波形四条放一起看幅值和冲击密度波形都看不出差别的话后面的时频图也基本救不回来。第三步STFT 扫 16、32、64 三档窗长用四种状态能不能分开当判据定下 32。第四步CWT 扫四个小波基定cmor1.5-2再用 32、64、128、256 扫尺度定 128。第五步按轴承几何参数算出内圈、外圈、滚珠的理论特征频率在最终图上标参考线逐个确认亮带位置是否落在线上。这五步里最容易被跳过的是第五步也是最不该跳的。前四步产出的都是看起来有差异的图只有把理论特征频率标上去差异才变成证据。我一般还会多做一件事把正常基线用完全相同的参数跑一遍两张图叠着看基线在哪个位置也亮那个位置就划掉——这一步能挡掉八成假阳性。6.2 一句实在话回过头看这套参数本身没什么稀奇真正花时间的是那些不报错的错误图题和参数错位、键名写死、中心频率被注释、版本接口对不上、把工频谐波当成故障特征。每一个都能让你在错误的结论上多站半天还自信满满。从那以后我每次跑时频分析都强制走一遍标题绑定变量、基线同参数对照、理论频率标线这三件事哪怕只出一张图。希望帮到你。本文还有配套的精品资源点击获取