news 2026/9/1 3:00:26

CWRU轴承数据集深度解析:Python处理与故障诊断实战指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
CWRU轴承数据集深度解析:Python处理与故障诊断实战指南

简介:凯斯西储大学(CWRU)轴承数据集是机械故障诊断领域的经典基准资源,涵盖正常、内环故障、外环故障、滚珠故障等多种工况的振动信号,适用于滚动轴承故障识别与诊断研究,可满足故障诊断初学者、设备健康管理研究者及机器学习建模人员的不同需求。资源包共172个文件,以165个.mat振动信号数据文件为主体,另含3个Python整理脚本、2个pyc辅助程序和2个txt使用说明,整体大小230.77MB,数据格式规整、目录结构清晰。配套Python程序覆盖原始数据读取、信号预处理、特征提取到故障模式识别的完整流程,能帮助用户高效完成数据整理与分析,避免下载文件格式不符、路径配置错误等常见问题;数据样本丰富,适合开展特征工程与分类模型验证。目前已有24495人学习下载,适合希望快速上手CWRU数据集、专注故障诊断算法研究与工程应用的中高阶用户。 每次带新手做故障诊断项目,我第一件事就是让他们先把CWRU轴承数据集的结构吃透。原因很简单——这是目前全球学术界最常用的滚动轴承故障诊断基准数据集,从朴素贝叶斯到最新的Transformer,几乎所有算法论文都会用它做验证。这个由美国凯斯西储大学轴承数据中心发布的经典数据集,包含正常、内圈故障、外圈故障、滚动体故障四大类状态,覆盖多工况、多损伤尺寸、多采样频率,拿到手就相当于拥有了一个标准化的“轴承故障实验室”。这篇文章就来聊透它:mat文件里到底藏了哪些数据、文件编号怎么破译、如何用Python批量解析和构造数据集,以及我在实际做研究时踩过的坑和验证过的可靠套路。不管你是刚入门想做复现的新手,还是已经跑过不少实验的老手,照着做都能少走弯路。

1. CWRU轴承数据集全景解读

1.1 实验装置与数据采集逻辑

先把这个数据集的“出身”讲清楚。这个实验是在凯斯西储大学的专用试验台上完成的,整个台架由电机、扭矩传感器/编码器、测功机以及控制电子设备组成。被测轴承安装在电机轴两端,一个是驱动端,一个是风扇端,型号是6205-2RS JEM SKF深沟球轴承。驱动端和风扇端各布置了加速度计,分别采集驱动端振动信号(DE列)和风扇端振动信号(FE列),部分数据还采集了基座振动信号(BA列)。

采样频率有两个档位:12kHz和48kHz。这个选择对后续处理影响很大,同一个故障在不同采样率下,序列长度和频率分辨率完全不同。实验还设置了4种负载工况:0马力(约1797转/分)、1马力(约1772转/分)、2马力(约1750转/分)、3马力(约1730转/分)。

注意:CWRU数据集里还有一个“驱动端正常基线数据”,文件名带后缀_0,很多人第一次跑的时候会忽略,导致训练集里缺少正常类别。后面解析文件时我会专门演示怎么处理。

1.2 故障类型与文件命名规则

这是新手最容易懵的部分。CWRU数据包里有大约270个mat文件,文件名从97.mat300.mat不等,表面看毫无规律,其实每个数字都对应一组实验条件。故障类型包括:

文件范围(示例)故障类型故障直径(英寸)负载(马力)采样位置备注
97、98、99、100正常0-3驱动端/风扇端97是12k驱动端,98是48k驱动端
105、118、130、144、158内圈故障(IR)0.007、0.014、0.0210-3驱动端105=IR 0.007" 0HP 12k
169、185、197滚动体故障(B)0.007、0.014、0.0210-3驱动端数字分布较广
234、237、240外圈故障(OR)中心@6:000.007、0.014、0.0210-3驱动端外圈故障还分方向
209、222外圈故障正交@3:000.007、0.014、0.0210-3驱动端方向不同特征不同

外圈故障有3个方向:中心(Centered,负载区@6:00)、正交(Orthogonal,@3:00)、反向(Opposite,@12:00)。这也是CWRU数据的一个隐藏特点——同样是外圈故障,方向不同振动传播路径不同,特征差异很明显。

文件名解析这件事千万别用“猜的”,我见过太多人把105当成内圈0.007英寸,结果用错标签不说,跑出来的混淆矩阵还“看起来很好”,实际上是标签错位了。正确做法是写一个解析函数,从文件名映射出完整工况条件,再结合文件内容校验,这个我放在后面代码里。

2. Python处理方案:从原始mat到可训练数据集

2.1 数据结构剖析:mat文件里到底装了什么

scipy.io.loadmat读一个常规的12k驱动端文件,会得到一个dict,里面字段包括:DE(驱动端加速度)、FE(风扇端加速度)、BA(基座加速度)、以及相关转速等元数据。但不同文件的字段名有差异——有些风扇端文件的字段是fan_DE,有些文件名带_0后缀代表正常基线数据。48kHz文件同样有DE列但可能没有FE列。

这是第一个关键坑:字段名不统一。不能硬编码字段名来批量读取,必须写成动态判断逻辑,先打印keys(),再确定通道。

还有一个细节:每个样本其实是在等时间间隔内采集的连续信号,长度通常在10秒到60秒不等,12kHz采样率下12万到几十万个点。做分类时不能直接喂几十万维序列给模型,需要做滑窗分段。

2.2 批量解析代码:一次干净地读完全部数据

下面是我常用的解析参考代码,经过多次打磨,可以直接用:

import os import numpy as np import pandas as pd from scipy.io import loadmat def parse_cwru_filename(filename): """ 从CWRU文件名中解析出核心信息。 返回字典:数字编号、位置、故障类型、损伤直径、负载、采样率。 """ name = filename.replace('.mat', '').replace('_0', '_NORMAL_0') parts = name.split('_') info = {} info['orig_num'] = parts[0] # 数字在186-190附近的一般是滚动体,在197-222附近一般外圈 num = int(parts[0]) if num in [97, 98, 99, 100]: info['fault'] = 'NORMAL' info['location'] = 'DE' if 'DE' in name else 'FE' else: # 根据实验记录表映射 if num in [105, 106, 118, 119, 130, 131, 144, 145, 158, 159]: info['fault'] = 'IR' elif num in [169, 170, 171, 185, 186, 187]: info['fault'] = 'B' else: # 外圈 info['fault'] = 'OR' # 继续补充负载、尺寸等字段 return info # 批量读取某个目录下所有12k驱动端mat文件 def load_cwru_batch(mat_dir, wanted_channels=None): """ 返回一个完整的DataFrame,列包含DE/FE/BA、标签、工况信息。 """ data_rows = [] for fname in sorted(os.listdir(mat_dir)): if not fname.endswith('.mat'): continue info = parse_cwru_filename(fname) mat = loadmat(os.path.join(mat_dir, fname)) keys = [k for k in mat.keys() if not k.startswith('__')] # 字段名确定逻辑 channel_map = {} for key in keys: if 'DE' in key or 'FE' in key or 'BA' in key: channel_map[key] = mat[key] # 将数据写入 row = {'filename': fname, **info} data_rows.append(row) # 这里只记录了元数据,实际数据可另存 return pd.DataFrame(data_rows)

这段代码的关键是parse_cwru_filename函数——它把“数字→故障类型”的映射规则集中起来,避免在数据分析环节东拼西凑。实际使用时,你还要把DE信号取出来进行滑窗切分,生成样本和标签。我通常的做法是:每段连续信号按1024或2048点为一个窗口、步长512切分,这样单样本既保留了足够周期特征,又不会让数据量爆炸。

2.3 滑窗切分与标签生成

滑窗切分不是无脑切。要知道,同一段连续振动信号里,前一部分和后一部分来自同一个实验,如果不做随机化直接放进训练集,和测试集之间会存在“相邻片段泄漏”——模型学会了背样本id而不是学特征。正确做法是:按文件来分train/test,而不是按窗口来分。比如把0马力所有文件放训练集,3马力所有文件放测试集,这样能验证泛化性。

def split_windows(signal, window_size=1024, step=512): windows = [] start = 0 n = len(signal) while start + window_size <= n: windows.append(signal[start:start + window_size]) start += step return np.array(windows) def make_dataset_from_mat(mat_path, fault_label, channel='DE', window_size=1024, step=512): mat = loadmat(mat_path) key = [k for k in mat.keys() if channel in k][0] sig = mat[key].flatten().astype(np.float32) windows = split_windows(sig, window_size, step) labels = np.full(len(windows), fault_label, dtype=np.int64) return windows, labels

这里窗口大小我推荐1024,因为12kHz下对应约0.085秒,刚好覆盖几十个轴承转频周期,足够提取特征。如果要跑时频分析,256或512也行,但越小噪声越大。

3. 核心细节解析与实操要点

3.1 为什么要做“工况级别”的数据划分

这个问题我在带学生和做论文实验时反复讲:CWRU数据集如果不加处理直接随机切分,模型准确率几乎都能到99%以上,但这不代表模型有泛化能力。原因在于同一文件切出来的窗口高度相关,随机切分会把同一个实验的相邻片段同时扔进训练和测试。测试集里的样本是训练集样本的“近亲”,相当于开卷考试。

所以我建议做法是:

  1. 按文件/实验条件划分,不在文件内部分窗口;
  2. 做跨工况实验,比如用0、1、2马力训练,3马力测试,检验模型的转速适应能力;
  3. 如果想比较不同算法的优劣,固定统一划分策略,保证公平。

3.2 样本类别不均衡问题

CWRU数据虽然各类别都有,但不同故障尺寸、不同负载下的样本量并不均衡。特别是正常数据只有3个文件对应多个故障文件,切窗后正常类样本远少于故障类。处理不平衡的方式包括过采样少数类、欠采样多数类、使用加权损失函数、或者做数据增强。在CWRU上我个人的经验是:使用类别权重比直接重采样要稳,因为重采样容易引入重复样本,导致过拟合。

3.3 信号预处理:降噪、归一化与去趋势

振动信号在采集过程中会受到传感器噪声和工频干扰影响,虽然CWRU数据质量算好的,但直接喂原始波形给深度学习模型时,最好还是做两步预处理:

  1. 归一化:常用的有Z-score标准化(减均值除标准差)或min-max归一化到[-1, 1];
  2. 去趋势:消除传感器零点漂移,用一阶差分或减去滑动平均。

对传统机器学习特征来说,这步特别重要。比如峭度、均方根这些时域特征,受趋势项影响很大,如果不先去趋势,特征值会失真。

4. 实操过程与核心环节实现

4.1 最小复现:5分钟跑通一个分类baseline

这里我用最经典的方式给大家演示:手工特征+随机森林,作为一个可靠的baseline。虽然现在的论文都上深度学习,但baseline的价值在于快速验证数据加载正确性。

import numpy as np from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import StandardScaler from sklearn.metrics import accuracy_score, classification_report def extract_features(win): """从一维窗口提取时域特征。""" feats = [] feats.append(np.mean(win)) feats.append(np.std(win)) feats.append(np.max(np.abs(win))) feats.append(np.sqrt(np.mean(win**2))) # RMS # 峭度 mu = np.mean(win) sigma = np.std(win) + 1e-12 feats.append(np.mean((win - mu)**4) / (sigma**4)) # 峰峰值 feats.append(np.ptp(win)) # 波形因数 feats.append(np.sqrt(np.mean(win**2)) / (np.mean(np.abs(win)) + 1e-12)) return np.array(feats) # 假设已经加载好windows和labels # X = np.array([extract_features(w) for w in windows]) # y = labels # 按工况划分后 # clf = RandomForestClassifier(n_estimators=200, random_state=42) # clf.fit(X_train, y_train) # pred = clf.predict(X_test) # print(accuracy_score(y_test, pred))

这个流程一跑,准确率通常在85%~98%之间(取决于工况划分的难度),如果低于这个范围,大概率是数据加载或标签映射有bug。你可以把这个当作“数据是否读对”的冒烟测试。

4.2 进阶:用1D-CNN直接学原始信号

手工特征需要人工经验,深度学习则让模型自己学特征。如果你有GPU环境,可以跑一个轻量级的1D-CNN,这是我实测下来非常稳定的结构:

import torch.nn as nn class CWRU_1DCNN(nn.Module): def __init__(self, num_classes=4, input_len=1024): super().__init__() self.conv1 = nn.Sequential( nn.Conv1d(1, 16, kernel_size=64, stride=8), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2)) self.conv2 = nn.Sequential( nn.Conv1d(16, 32, kernel_size=3, stride=1, padding=1), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2)) self.conv3 = nn.Sequential( nn.Conv1d(32, 64, kernel_size=3, stride=1, padding=1), nn.BatchNorm1d(64), nn.ReLU(), nn.MaxPool1d(2)) # 动态计算flatten维度 self._flatten_len = None self.fc = None self._build_fc(input_len) def _build_fc(self, input_len): dummy = torch.zeros(1, 1, input_len) x = self.conv1(dummy); x = self.conv2(x); x = self.conv3(x) self._flatten_len = x.view(1, -1).size(1) self.fc = nn.Linear(self._flatten_len, 4) def forward(self, x): x = x.unsqueeze(1) x = self.conv1(x); x = self.conv2(x); x = self.conv3(x) x = x.view(x.size(0), -1) return self.fc(x)

我在多个配置下跑过,用Adam优化器、学习率1e-3、训练30个epoch,分类准确率能稳定到98%以上。如果你想复现代码,注意cnn第一层的kernel_size不宜太小,64能抓到单个冲击的特征;太大则计算量上升,训练变慢。

4.3 数据增强与泛化提升

想让模型在实际场景里更鲁棒,可以给CWRU数据加点“真实感”。我尝试过的有效增强包括:

  • 加高斯噪声:SNR在10~20dB之间,模拟环境噪声;
  • 时间偏移:随机平移几个采样点,模拟触发时刻不同;
  • 幅值缩放:随机乘一个0.9~1.1之间的系数,模拟传感器安装松紧带来的增益变化。

这些增强方法在跨工况实验中都稳定带来了2~5个百分点的提升,但注意增强幅度别太大,太大反而引入偏差。

5. 常见问题与排查技巧实录

5.1 踩坑记录:加载、标签、采样率

问题现象原因分析解决方案
loadmat报错NotImplementedError: Please use HDF readermat文件是v7.3版本,CWRU部分新打包版本可能使用hdf5格式h5py读取;或者检查文件版本是否v5/v7。CWRU官网下载的经典mat是v5格式,直接用loadmat没问题
明明跑了个模型,准确率超高但换个工况就崩按窗口随机切分导致数据泄漏改为按文件/工况划分数据,确保训练测试无重叠片段
解析文件名时_0正常数据被当成故障数据正常数据带_0后缀,而部分故障文件名没有该标记在解析函数里统一处理_0后缀,显式映射为NORMAL
12k和48k数据混在一起,形状不同报错采样率不同,序列长度差异大统一重采样到指定采样率,或分开建模。不能用一份代码同时处理两种采样率的数据而不做长度对齐

5.2 避坑清单:那些文档里没写明的陷阱

  • 不要相信文件名排序即标签顺序。CWRU的编号不是严格递增映射,中间有正常基线数据插入、有故障方向分类,必须用官方实验记录表逐一确认。
  • 字段名差异。有的mat文件里是DE,有的可能是fan_DE;有的BA字段在部分文件里缺失。写代码时要做容错,用try/except缺失值丢弃处理。
  • 类别不平衡。如果训练脚本里没有设置class_weight或采样策略,把正常类单独抽取出来测试时,精准率会非常难看。
  • 训练前先检查数据形状和范围。我习惯在加载后立刻打印出一个样本的shapedtypemin/max,这一步能拦住90%的脏数据问题。
  • 窗口重叠率不要太大。虽然重叠可以增加样本,但重叠率过高会让训练集和验证集之间产生相关性,导致验证曲线失真。推荐重叠率在50%左右即可。

5.3 几个提高效率的工程技巧

CWRU数据总量不大(几百MB),完全可以一次性load进内存。但当你做超参搜索时,频繁读取mat文件会非常慢。我的经验是:第一次解析完就把所有窗口数据存成npy或h5文件,后续实验直接读npy,能节省80%的数据加载时间。

import h5py # 保存成h5 with h5py.File('cwru_windows.h5', 'w') as f: f.create_dataset('X', data=X_all) f.create_dataset('y', data=y_all) f.create_dataset('condition', data=condition_ids)

另外,我在实际项目中经常会把DE、FE通道混合使用,因为某些故障在驱动端表现不明显,在风扇端更清晰。如果你只做四分类基础实验,用DE单通道就足够了;如果做故障尺寸或位置细粒度分类,建议把多通道拼成多输入,模型鲁棒性会好很多。

最后再分享一个小技巧:CWRU数据集里外圈故障因为有3个安装方向,很多论文其实只用了其中一种方向,导致对比不公平。你在跟自己或他人的方法做对比实验时,务必在论文里写明用了几种方向、哪些工况、窗口大小、划分方式,否则结果完全不可比。这个数据集的“标准”只是采集方式标准,使用方式上并没有金标准——恰恰是谁能讲清楚数据处理细节,谁的结果更经得起推敲。

本文还有配套的精品资源,点击获取

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/1 2:58:37

一级能效72%热效率燃气灶,嵌入式安装避坑指南

家里燃气灶退役&#xff0c;很多人第一眼就会被“一级能效嵌入式天然气灶具”“72%热效率”“双灶联动”“智能大火力”“节能猛火”这串词吸引。我的建议是&#xff1a;先别急着下单&#xff0c;先弄清楚这些词在你的厨房里到底意味着什么。嵌入式天然气灶具不是看谁文案写得猛…

作者头像 李华
网站建设 2026/9/1 2:58:09

智慧社区老人安全监护系统:从跌倒检测到告警闭环的设计实践

一个独居老人如果在家摔倒&#xff0c;最怕的不是摔倒本身&#xff0c;而是摔完之后没有人知道。许多智慧社区项目启动时&#xff0c;第一件想做的事就是给老人家里装摄像头和报警器。可实际项目里真正能稳定用起来的不多&#xff1a;要么告警全量堆在群里没人看&#xff0c;要…

作者头像 李华
网站建设 2026/9/1 2:57:13

基于LSTM与Encoder-Decoder的UCF101视频动作识别实战

简介&#xff1a;结合LSTM的encoder-decoder模型在UCF101动作识别任务中的完整实践包&#xff0c;面向视频分类初学者与进阶研究者&#xff0c;旨在解决时序动作建模、长程依赖捕捉与特征融合问题。压缩包为7z格式&#xff0c;共90个文件&#xff0c;整体8.93MB&#xff0c;包含…

作者头像 李华
网站建设 2026/9/1 2:56:14

RAG的9种架构,你用的是哪一种?

最近总有人问我&#xff0c;RAG 到底怎么做。 我说你具体想做什么。 十有八九&#xff0c;对方描述的是同一个东西&#xff1a;把文档切块、做向量化、存进向量数据库&#xff0c;用户提问的时候检索出最相关的几段&#xff0c;拼进 prompt 丢给大模型。 我说&#xff0c;这…

作者头像 李华
网站建设 2026/9/1 2:53:02

LLM与经典机器学习协同实战:从特征工程到文本分类

最近在做一个文本风控项目时&#xff0c;团队里争论了一个很有意思的问题&#xff1a;既然大语言模型&#xff08;LLM&#xff09;已经能读懂长文本、能写摘要、能做情感分析&#xff0c;那我们为什么还要保留 XGBoost、逻辑回归这些经典机器学习模型&#xff1f;干脆全换成 LL…

作者头像 李华
网站建设 2026/9/1 2:52:31

Java Web商城项目实战:从解压部署到上线优化的完整指南

简介&#xff1a;一份基于Servlet、JSP、JDBC、jQuery和Ajax的Java Web商城项目&#xff0c;采用MVC分层与面向接口编程思想&#xff0c;适合初学JavaWeb的开发者作为综合练习、毕业设计或课程设计参考。项目覆盖商品展示、购物车、订单处理、用户登录注册、商品评论、新闻公告…

作者头像 李华