
简介这份数据集面向从事电机故障诊断的工程师、设备维护人员及高校研究人员系统整理了转子偏心、轴弯曲、转子条断裂、电机缺相、轴承故障、匝间短路、转子不平衡等七类典型故障的频谱特征可作为振动分析入门与现场排查的对照参考。资源包内含1个docx文档约608KB以表格与文字结合的方式归纳各类故障的特征频率、边带规律及诊断建议便于快速查阅与比对。目前已有947人学习下载说明其在电机状态监测领域具有一定实用价值。读者可从中获取各故障对应的频谱判据例如两倍行频、极通过频率边带、1X主导成分等关键指标并了解匝间短路需借助电路分析而非振动信号监测的差异从而提升故障定位效率也可作为开发智能诊断系统的数据素材。1. 故障电机典型频谱特征整理数据集从振动信号到可训练样本的落地路径一台 7.5kW 三相异步电机在试验台上跑到 70% 额定负载时加速度传感器采到的时域波形看不出任何异常但把同一段信号做 FFT 之后在 2 倍电源频率附近冒出一根明显抬升的边带——这类时域平静、频域露馅的场景正是故障电机典型频谱特征整理数据集要解决的核心问题。它本质上是一份把电机常见故障轴承内圈/外圈剥落、转子断条、定子绕组匝间短路、气隙偏心、不对中对应的振动频谱特征按统一采样规范、统一标签体系整理成结构化样本的数据集让做设备预测性维护的工程师能直接拿去训练分类模型或做规则阈值标定。适合两类人一是手上只有原始振动采集、缺标注的运维算法工程师二是想验证自己特征提取流程是否靠谱的故障诊断方向开发者。数据集不是万能的它最大的价值在于把频谱长什么样算哪种故障这件事从老师傅的经验里抠出来变成可复现、可对比的数值。2. 频谱特征到底怎么变成一条样本采集、变换与标签设计2.1 从时域到频域为什么故障特征藏在频谱里电机故障的物理机理决定了它的振动能量会集中在特定频率上。轴承外圈剥落时滚珠每次碾过缺陷点会产生一次冲击冲击的重复频率就是外圈故障特征频率 BPFO转子断条会让转子回路不对称在电源频率两侧调制出 (1±2s)f₁ 的边带气隙偏心则会在 2 倍电源频率处产生异常分量。这些频率成分在时域里被噪声淹没只有通过频谱分析才能把能量重新分配到频率轴上让特征显形。所以整理数据集的第一步不是采集而是想清楚我要保留哪些频率分辨率、哪些频段。常见做法是采样率取 1020 kHz覆盖到 5 倍以上最高关注频率避免混叠频率分辨率 Δf fs/NN 取 8192 或 16384对应 Δf 约 1.2 Hz 或 0.6 Hz足够分辨边带间隔。如果分辨率太粗断条边带和主频会糊在一起模型学到的就是噪声。2.2 一条样本的字段设计我一般会保留这 6 个维度数据集不是只存一张频谱图就完事。为了让下游既能做深度学习也能做传统特征工程每条样本我建议保留以下字段字段名类型说明sample_idstring唯一编号建议含工况信息raw_signalfloat32[]原始时域波形长度 8192/16384spectrumfloat32[]单边幅值谱长度 N/2fault_labelint故障类别编码0 为健康severityfloat故障严重程度01 归一化rpmfloat采集时转速用于频率归一化其中 severity 这个字段很多人会忽略但它是区分早期微弱故障和晚期明显故障的关键。没有它模型会把所有同类故障当成一个模式实际部署时早期故障根本检不出来。2.3 标签体系怎么定别把多故障混采当成单标签真实电机很少只坏一处。轴承故障往往伴随不对中断条可能引发偏心。如果数据集强行给每条样本打单一标签模型上线后遇到复合故障就会乱判。我的做法是采用多热编码multi-hot同时保留一个主故障标签用于分层采样。下面是一段把原始采集目录整理成标准样本的 Python 脚本骨架import numpy as np import os import json from scipy.fft import rfft, rfftfreq FS 12000 # 采样率 Hz N 8192 # 每段点数 FAULT_MAP { # 故障类别编码 healthy: 0, bearing_inner: 1, bearing_outer: 2, rotor_broken: 3, stator_short: 4, eccentricity: 5, misalignment: 6 } def load_segment(path): 读取一段时域信号要求单列 float 文本或 npy if path.endswith(.npy): sig np.load(path).astype(np.float32) else: sig np.loadtxt(path, dtypenp.float32) if len(sig) N: raise ValueError(f{path} 长度不足 {N}) return sig[:N] def to_spectrum(sig): 单边幅值谱做汉宁窗抑制泄漏 win np.hanning(len(sig)) spec np.abs(rfft(sig * win)) / (len(sig) / 2) return spec.astype(np.float32) def build_sample(sig, label_name, severity, rpm): spec to_spectrum(sig) return { sample_id: f{label_name}_{rpm:.0f}_{np.random.randint(1e6):06d}, raw_signal: sig.tolist(), spectrum: spec.tolist(), fault_label: FAULT_MAP[label_name], severity: float(severity), rpm: float(rpm) } if __name__ __main__: root ./raw_data samples [] for fault in os.listdir(root): for f in os.listdir(os.path.join(root, fault)): sig load_segment(os.path.join(root, fault, f)) # severity 和 rpm 建议从文件名或旁路元数据读取 samples.append(build_sample(sig, fault, severity0.5, rpm1480)) with open(dataset.json, w) as fp: json.dump(samples, fp) print(f共生成 {len(samples)} 条样本)这段脚本的逻辑很直白统一截断到固定长度、加汉宁窗做 FFT、把时域和频域都存下来。参数上FS必须和实际采集卡一致写错会导致所有特征频率整体偏移N决定频率分辨率8192 在 12 kHz 采样下给出约 1.46 Hz 分辨率对 50 Hz 电源系统的边带分析够用。np.hanning窗会略微展宽主瓣但能压住频谱泄漏避免边带被主频旁瓣淹没——这是很多人第一次做频谱整理时翻车的地方。2.4 频率归一化让不同转速的样本能放在一起训同一台电机在 900 rpm 和 1480 rpm 下采到的故障特征频率完全不同。如果直接拿原始频率轴去训练模型会先学转速、再学故障泛化很差。常见做法是把频率轴除以转频转成阶次order这样轴承故障特征就固定在 BPFO/转频 这个比值上。整理数据集时我一般会额外存一列 order_spectrum或者至少把 rpm 字段留好让下游自己转。这一步不做数据集在变转速工况下基本废掉一半。3. 用整理好的数据集跑通一个基线分类器从加载到评估3.1 数据加载与划分按工况分层别随机切拿到 dataset.json 之后第一件事是划分训练/验证/测试集。如果直接train_test_split(random_state42)同一段连续采集被切到两边验证集准确率会虚高到 99%上线就崩。正确做法是按采集批次或按转速工况做分组划分。下面这段代码演示按 rpm 分层import json import numpy as np from sklearn.model_selection import GroupShuffleSplit with open(dataset.json) as fp: data json.load(fp) X np.array([d[spectrum] for d in data], dtypenp.float32) y np.array([d[fault_label] for d in data]) groups np.array([round(d[rpm] / 100) for d in data]) # 按转速分桶 gss GroupShuffleSplit(n_splits1, test_size0.3, random_state0) train_idx, test_idx next(gss.split(X, y, groups)) X_train, X_test X[train_idx], X[test_idx] y_train, y_test y[train_idx], y[test_idx] print(f训练集 {len(X_train)} 条测试集 {len(X_test)} 条)GroupShuffleSplit保证同一转速桶的样本不会同时出现在训练和测试里这样评估出来的准确率才接近真实换工况场景。test_size0.3是经验值样本量少于 2000 条时可以放到 0.2但别低于 0.15否则测试集统计波动太大。3.2 基线模型先上逻辑回归别一上来就堆 CNN很多人拿到频谱数据第一反应是搭一维卷积网络。我的血泪经验是先用逻辑回归或 SVM 跑一个基线确认特征本身可分再决定要不要上深度模型。如果线性模型都能到 90%说明频谱特征很干净深度模型提升空间有限如果线性模型只有 60%再去看是特征没对齐还是标签有问题。from sklearn.linear_model import LogisticRegression from sklearn.preprocessing import StandardScaler from sklearn.pipeline import make_pipeline from sklearn.metrics import classification_report clf make_pipeline( StandardScaler(), LogisticRegression(max_iter2000, C1.0, multi_classmultinomial) ) clf.fit(X_train, y_train) pred clf.predict(X_test) print(classification_report(y_test, pred, digits3))StandardScaler对频谱幅值做零均值单位方差避免高频段小幅值被低频段大幅值压制。C1.0是正则强度频谱维度高4096 维时容易过拟合可以降到 0.1 试试。max_iter调到 2000 是因为高维数据下默认 100 次往往不收敛会报 ConvergenceWarning——这不是模型坏了是迭代不够。3.3 看混淆矩阵故障类别之间的混淆才是真问题准确率只是一个数真正有价值的是看哪两类在互相混。轴承内圈和外圈故障在包络谱上区别明显但在原始幅值谱上可能因为边带重叠而混淆转子断条和偏心都表现为电源频率附近的调制也容易混。整理数据集时如果发现这两类混淆严重说明要么频率分辨率不够要么需要补包络谱特征。下面这段代码把混淆矩阵打出来from sklearn.metrics import confusion_matrix import numpy as np cm confusion_matrix(y_test, pred) labels [healthy, inner, outer, rotor, stator, ecc, misalign] print( .join(f{l:8} for l in labels)) for i, row in enumerate(cm): print(f{labels[i]:8} .join(f{v:8d} for v in row))如果发现 inner 和 outer 互相混优先检查 BPFO 和 BPFI 是否在频率轴上分得开——这直接回到 2.1 节的频率分辨率问题。数据集整理阶段埋的坑模型阶段一定会暴露。4. 避坑与排查整理频谱数据集时最容易翻车的 5 件事4.1 现象所有样本频谱在 50 Hz 处都有一根巨峰模型只学这一根原因采集时没有做去趋势或没有滤掉工频干扰50 Hz 电源频率及其谐波能量远大于故障特征标准化之后仍然主导方差。解决在 FFT 之前加一个 50 Hz 陷波滤波器或者在做完频谱后把 50 Hz 及其 2、3 次谐波附近 ±2 Hz 的谱线置零。注意别把边带一起抹掉断条特征就在 50 Hz 两侧。4.2 现象训练集准确率 99%测试集 60%原因按随机方式切分同一段连续采集的相邻样本同时进了训练和测试模型记住了这段信号的噪声指纹而不是故障特征。解决按采集批次或转速分组切分参考 3.1 节的 GroupShuffleSplit。如果数据本身就是一段长信号切出来的至少保证切分边界有重叠丢弃。4.3 现象severity 字段全是 0.5模型分不清早期和晚期故障原因整理时图省事没有从元数据里读取故障注入程度统一填了默认值。解决如果原始采集没有 severity 记录可以用故障特征频率处的幅值相对于健康基线的抬升倍数做代理指标归一化到 01。这个代理不完美但比常数强。4.4 现象不同采集批次的频谱幅值量纲差十倍原因传感器灵敏度、放大器增益、采集卡量程在不同批次间不一致整理时没有做幅值归一化。解决每条样本的频谱除以自身总能量L2 范数或除以健康基线在相同工况下的频谱做相对幅值。绝对幅值只在同一批次内可比。4.5 现象数据集里健康样本远多于故障样本模型全预测健康也有 85% 准确率原因故障电机采集成本高健康数据容易攒类别不平衡是常态。解决训练时用 class_weightbalanced评估时看宏平均 F1 而不是准确率。整理数据集时也可以在文档里明确标注类别分布让下游心里有数。5. 进阶技巧用阶次谱和包络谱把弱故障从噪声里捞出来整理到这一步基础数据集已经能跑通分类。但如果你面对的是早期微弱故障——特征频率处幅值只比噪声底高两三个 dB——单靠原始幅值谱还是不够。我一般会补两个衍生特征阶次谱和包络谱。阶次谱的做法是把频率轴除以转频得到无量纲的阶次轴。这样同一故障在不同转速下的特征会对齐到同一阶次位置模型不用再学转速。实现上先对时域信号做角域重采样需要转速脉冲或转速估计再 FFT。如果没有转速脉冲可以用谱峭度法估计转频但精度会打折。包络谱更适合轴承故障。轴承冲击是高频调制信号直接看幅值谱会被其他低频成分淹没。做法是先带通滤波到轴承共振频带通常 25 kHz再做希尔伯特变换取包络最后对包络做 FFT。包络谱上 BPFO、BPFI 及其谐波会非常干净地冒出来。下面是一段包络谱提取的代码from scipy.signal import butter, filtfilt, hilbert from scipy.fft import rfft, rfftfreq def envelope_spectrum(sig, fs, band(2000, 5000)): 带通滤波 希尔伯特包络 FFT b, a butter(4, [band[0]/(fs/2), band[1]/(fs/2)], btypeband) filtered filtfilt(b, a, sig) env np.abs(hilbert(filtered)) env env - np.mean(env) # 去直流 spec np.abs(rfft(env)) / (len(env) / 2) freqs rfftfreq(len(env), 1/fs) return freqs, spec.astype(np.float32)band的选择是这套方法里最玄学的一步。选窄了共振频带没覆盖全包络里冲击成分弱选宽了噪声进来把包络淹没。我一般会先对健康信号做谱峭度图找峭度最大的频带作为带通范围。butter的阶数取 4 是折中阶数太高会引入相位失真阶数太低阻带衰减不够。filtfilt做零相位滤波避免包络时间偏移。把包络谱和阶次谱都整理进数据集之后你会发现原本混在一起的内圈/外圈故障在包络谱上分得很开因为 BPFO 和 BPFI 的数值差异在包络域被放大了。代价是数据集体积会涨——每条样本多存两列频谱。我的习惯是原始幅值谱、包络谱、阶次谱各存一份让下游按任务选而不是替他们做决定。最后说一个我踩过的坑包络谱的幅值量纲和原始谱完全不同如果混在一起做标准化包络谱会被原始谱的大幅值压成一条平线。正确做法是分别标准化或者干脆分成两个输入通道。这个细节不写进数据集文档里下游十有八九会翻车。希望帮到你。本文还有配套的精品资源点击获取