CWRU轴承数据集整理与Python程序使用全攻略

发布时间:2026/10/13 19:50:21
CWRU轴承数据集整理与Python程序使用全攻略 简介凯斯西储大学CWRU轴承数据集是机械故障诊断领域的经典公开资源面向故障诊断研究人员、设备维护工程师及机器学习学习者用于滚动轴承内环、外环、滚珠等典型故障的模式识别与状态监测。压缩包共172个文件以165个MAT格式振动信号数据为主涵盖多种驱动端转速和故障直径下的正常与故障样本另含3个Python数据整理分析脚本及2个TXT使用说明可帮助用户完成数据加载、信号预处理和特征提取规避下载与处理中的常见问题。资源整体约230.77MB目录结构清晰数据与脚本配套便于直接开展对比实验结合说明文档可快速理解数据组织方式。目前已有24538人学习下载是入门轴承故障诊断、验证机器学习或深度学习分类算法时值得参考的高质量基准数据集。1. CWRU轴承数据集是故障诊断入门的第一站先看清它到底给你什么做设备故障诊断或者学生研究旋转机械绕不开一个公开数据集——凯斯西储大学CWRU轴承数据中心发布的振动数据。它把电机驱动端和风扇端的加速度计信号按故障类型、故障直径、转速和负载组织成文件想验证算法、跑模型、写论文很多人第一站就是它。可等你真的把数据包下载下来会发现里面是一堆编号的 .mat 文件点名和文档对不上Python 读进来全是字典键标签得自己建。这篇文章照着标题里“数据包整理Python程序使用说明”三个部分讲清楚这个数据集怎么读、怎么整理成训练样本、参数怎么设、哪些地方最容易翻车。2. 认识数据包结构文件名编码、通道与负载是三个绕不开的门槛CWRU 数据包网上有多个整理版本常见结构是根目录下按故障类型分子文件夹或者直接摊开放一批 .mat 文件。不管哪种第一步都不是写代码而是把文件名和通道搞明白。否则整理出来的标签是错乱的模型训得再准也没有工程意义。2.1 文件名里的编码规则DE、FE、BA和故障直径怎么读CWRU 原始数据的常见命名方式是数字编号比如105.mat、118.mat、130.mat后面还有0.007、0.014、0.021这类直径描述。理解编号规则可以从官方说明文档里的表格入手但更实用的是记住故障类型和直径之间的关系。常见的故障代码格式有两种。一种是纯编号105.mat对应内圈故障 0.007 英寸、负载 0 hp118.mat对应外圈故障 0.007 英寸、负载 1 hp。另一种是带文字后缀的IR007_0、OR0146_2、B021_1含义很直白IR 是 inner race内圈OR 是 outer race外圈B 是 ball滚动体后面数字前三位是故障直径6表示外圈故障点所在负荷区的位置角度。整理程序里我一般会优先解析这种后缀因为它直接告诉你标签。读 mat 文件时文件内部变量名也有约定。常见的有DE_time驱动端加速度计、FE_time风扇端、BA_time基座加速度计各个通道都是一维数组。所以标签信息只存在文件名里信号本身不会自带故障类型。这一步要建立一个映射表把每个文件名对应的故障类型、故障直径、负载、转速都收录进去。我的习惯是建一个字典手动维护这些映射而不是靠字符串切片因为编号文件名的规律在不同版本里不完全一致。2.2 12k与48k采样频率、驱动端与风扇端通道怎么选数据包里的采样频率常见两档12 kHz 和 48 kHz。驱动端轴承数据大多用 12k实际文件命名里如果没写可以从数组长度和记录时长反推。一个 10 秒的 12k 采样信号长度是 120000 个点左右48k 则是 480000 个点左右。你先看DE_time的长度除以 2基本就能确认采样频率档次。选通道要看你的应用场景。做驱动端轴承故障诊断优先用DE_time因为故障冲击传递路径短信噪比高风扇端FE_time适合做负载传递研究或者想对比多个通道融合的场景。BA_time也不是没用放在基座上能感知更全局的振动但少了故障点的近场冲击特征很多论文不推荐它做主要输入。我在实际项目里会把 DE 和 FE 都导出来分别存成独立文件后续做通道融合或者单通道对比都方便。整理程序里不要只挑一个通道写死留个参数channel让人切。常见做法是channel_map { DE: DE_time, FE: FE_time, BA: BA_time, }这样别人用你的整理程序时改一个字符串就能切换通道不用在代码里找半天哪里在赋值。2.3 数据包里的文件夹、mat与csv格式先盘点再动手官方发布的数据最初以 mat 文件为主后来社区也整理过 csv 版本。你拿到的“数据包”可能是三种情况纯 mat 文件、mat 加 csv 混合、带 Excel 索引表。开始写程序之前先跑一个文件清单find /path/to/cwru -name *.mat | sort | head -20这样能快速看到命名风格。不同格式读取路径不一样mat 用scipy.io.loadmatcsv 用pandas.read_csv如果 mat 是 v7.3 格式还得走h5py。所以数据包整理程序的第一步不是处理信号而是自动识别文件格式和版本否则第一次跑就崩溃。我用过的典型数据包里有三类文件正常轴承数据97.mat这种不带故障的故障数据带 IR/OR/B 后缀的以及文档README。整理时把正常数据单独放一个文件夹避免标签映射时混淆。把所有文件按名称排序后打印前 10 个文件名和对应的标签人眼确认一遍再往下走这是血泪经验标签错位的问题绝大多数出在排序规则和真实文件顺序不一致上。3. 用Python把.mat数据整理成故障诊断标准格式一个可复用的脚本思路理解了命名规则就可以写整理程序了。这一章不是给你一个黑匣子脚本而是把每一步逻辑拆开方便你按自己的数据包版本调整。3.1 环境准备与依赖库scipy、numpy、pandas的安装读 mat 文件至少需要scipy和numpy整理标签和最后存成规范数据集则用到pandas。环境干净的话直接装pip install numpy scipy pandas如果是在国内网络环境建议加-i https://pypi.tuna.tsinghua.edu.cn/simple这个镜像比默认源快很多。装完后在 Python 里验证一下import scipy.io import numpy as np print(scipy.__version__) print(np.__version__)这里有个容易踩的坑scipy版本太旧可能不支持某些带压缩标志的 mat 文件。我的建议是scipy1.8.0如果读取报ValueError: Unknown mat file version说明要么文件损坏要么碰到 v7.3 格式后者要用h5py解决。具体排查放后面的避坑章节这里先准备好环境就行。3.2 按文件批量读取mat从单一文件到完整数据集以最常见的DE_time为例先读一个文件from scipy.io import loadmat import numpy as np def load_single_mat(filepath, channelDE): mat loadmat(filepath) key fX{filepath.stem}_{channel}_time # 例如 X105_DE_time if key in mat: data mat[key].flatten() else: # 兼容不同命名风格 candidates [k for k in mat.keys() if channel in k and time in k] if not candidates: raise KeyError(f{filepath} 中找不到通道 {channel}) data mat[candidates[0]].flatten() return data这里filepath.stem是文件名去掉.mat后的部分比如105。CWRU 原始 mat 的内部变量名很多是X105_DE_time这种格式所以用变量名拼接最直接。但有些版本的文件变量名不带前缀或者通道名是DriveEnd这时候candidates那段兜底逻辑就起作用了。批量读取时要注意所有 mat 文件里通道的键名不一定统一。我会先在数据包根目录里随机抽三个文件打印loadmat(...).keys()看看有没有共同规律再决定用哪种解析。不要一上来就全量跑否则遇到命名冲突报错会浪费一整轮时间。批量循环一般这样写from pathlib import Path import pandas as pd data_root Path(CWRU) files sorted(data_root.glob(*.mat)) records [] for f in files: de load_single_mat(f, channelDE) fe load_single_mat(f, channelFE) label parse_label(f.name) # 从文件名提取故障类型 records.append({file: f.name, label: label, de: de, fe: fe})records直接放进内存可能很占空间12k 采样下每个文件十几万点几十个文件也就几百 MB现代机器没问题。如果你处理的是 48k 和多个通道一次性 load 全部会爆内存那就改成边读边切窗边写盘不要把所有原始信号都囤在列表里。3.3 切窗与标签映射把连续信号变成监督学习样本原始信号是一维长序列不能直接喂给 CNN 或者 Transformer。常见做法是滑窗切片每个窗口是一个样本。窗口长度要覆盖至少一个机械旋转周期转速 1797 rpm 时周期约 0.033 秒对应 12k 采样就是约 400 个点所以 1024 点是安全的如果转速更低建议用 2048 点。切窗代码如下def sliding_window(data, window_len1024, overlap0.5): step int(window_len * (1 - overlap)) n len(data) if step 0: raise ValueError(overlap 必须小于 1) windows [] for start in range(0, n - window_len 1, step): windows.append(data[start:start window_len]) return np.array(windows)参数说明overlap0.5表示相邻窗口重叠 50%这是故障诊断里比较常见的配置既能增加样本量又不至于让相邻窗口过于相似导致过拟合。如果样本量不够可以提升到 0.75如果追求独立样本用重叠 0。切完窗后每个窗口打上同样的标签def make_samples(data, label, window_len, overlap): windows sliding_window(data, window_len, overlap) labels np.full(len(windows), label, dtypenp.int32) return windows, labels标签映射建议用整数常量而不是字符串方便模型计算交叉熵LABEL_MAP {normal: 0, inner: 1, outer: 2, ball: 3}这里有个细节CWRU 的原始文档里经典分类任务有时用三种故障加上正常共四类。如果你想做更细的“故障直径 位置”分类标签数会变成几十个整理程序要支持从文件名解析出直径和负载。我的建议是先用四类跑通流程再慢慢扩充细粒度标签。3.4 训练集/测试集划分与数据增强别把同源窗口切进两边样本切好后最容易犯的错误是直接train_test_split(X, y, test_size0.2)。因为相邻窗口来自同一段信号前后相关性极强随机划分会让测试集里满是训练集的“近亲”验证准确率虚高。正确做法是按文件分组划分每个 mat 文件的所有窗口要么全进训练集要么全进测试集。代码可以这么写from sklearn.model_selection import GroupShuffleSplit groups np.array([i for i, _ in enumerate(files) for _ in range(num_windows_per_file[i])]) # 更标准的方式是把每个样本所属的原始文件编号存起来 splitter GroupShuffleSplit(n_splits1, test_size0.2, random_state42) train_idx, test_idx next(splitter.split(X, y, groupsgroups))这里groups必须对应每个样本来自哪个文件。如果不做分组准确率可能从 90% 直接虚高到 99% 以上等到了实机数据就露馅。数据增强方面常见做法是加一点高斯噪声或对窗口做小幅平移但 CWRU 数据本身比较干净我的经验是先不加增等模型在测试集上稳定后再评估噪声鲁棒性否则会把增强当成本文主题之外的一个大坑。4. 使用说明里的关键设定采样点数、重叠率、转速与故障直径怎么配数据包自带的“使用说明”往往会写一些默认参数但很多人直接照抄最后发现结果和论文对不上。这里把真正影响结果的几个参数单独拎出来讲。4.1 常用的1024/2048点窗长与重叠率选择窗长和重叠率一起决定了样本量和每条样本包含的故障冲击次数。CWRU 的转速在 1730 到 1797 rpm 之间故障特征频率通常不超过 300 Hz。以 1024 点窗长、12k 采样为例每个窗口时长约 85 ms约 2.5 个旋转周期足够看到至少两次外圈故障冲击。如果窗长降到 512 点42 ms一个旋转周期都覆盖不全故障特征容易被削弱。常见参数组合如下表场景窗长重叠率样本时长建议简单四分类102450%85ms首选细粒度直径分类204875%170ms保证每窗3个以上周期实时性要求高51250%42ms可能损失特征深度模型训练204850%170ms样本量够就选重叠率 50% 时样本量大概为原始信号长度除以 512。一个 12k 采样、10 秒的信号能切出约 230 个窗口四类数据几十个文件就上万样本够一个小型 CNN 用了。如果你觉得样本量不够拉高重叠率到 75% 样本量翻倍但要小心模型记住窗口边界。4.2 不同负载下转速变化对切窗的影响CWRU 数据包里负载分为 0、1、2、3 hp对应的转速分别是 1797、1772、1750、1730 rpm。转速变化直接影响故障特征频率但不会剧烈影响一维振动波形的基本形态。切窗时如果能按文件记录转速比如 105.mat 对应 1797 rpm最好把转速和故障直径一起写入标签表后续做可视化或计算特征频率时直接查表。有一个常被忽略的点不同负载下同一故障直径的信号幅值范围不同。比如 0 hp 下信号幅值偏小3 hp 下幅值明显变大。如果切窗后不归一化模型可能学到的是“负载差异”而不是“故障差异”。所以整理出的每个窗口建议做 z-score 标准化而不是 min-max 到 [0,1]。z-score 能保留振动波形的相对形状min-max 会被极端冲击点带偏。标准做法def zscore_window(win): mean win.mean() std win.std() if std 1e-8: return win - mean return (win - mean) / std4.3 数据标准化与归一化哪种方法适合CNN/Transformer对于 CNN 输入z-score 后数据均值接近 0标准差接近 1卷积核初始化更容易收敛。对于 Transformer输入是 1D 序列同样用 z-score因为 self-attention 对幅值敏感如果输入特征范围差异太大注意力权重会被某一维主导。CWRU 数据整理程序里我默认先做 z-score存成 numpy 数组等训练时再在Dataset类里按需调整。如果做频域分析标准化对象应该是幅值谱或者功率谱而不是时域窗。程序里我会把时域 z-score 和频域标准化分开写不要让一个函数同时处理两个域。一个简单的频域标准化是除以频谱的总能量得到归一化频谱。使用说明文档里如果提到了滤波比如带通 1kHz 到 10kHz也属于预处理的一部分但这一项不是必须的CWRU 数据本身带比较干净的振动信号直接用原始波形效果也可。5. CWRU数据集避坑指南四个常见的翻车现场与排查方法整理 CWRU 数据的过程中有几个坎几乎每个人都会踩。这里写四条最典型的每条按现象、原因、排查的思路来。5.1 mat文件版本太新导致读取失败现象scipy.io.loadmat报告ValueError: Unknown mat file version或者读出来的数组 dtype 不对全是mat73对象。原因CWRU 后期整理的数据包可能用 MATLAB R2015 以上版本导出存成了 v7.3 格式基于 HDF5普通loadmat不支持。早期的 v5 格式才可以直接读取。解决先判断格式。v7.3 文件头包含 HDF5 的魔数用h5py读取import h5py def load_mat_v73(filepath, keyDE_time): with h5py.File(filepath, r) as f: data f[key][()] return data.flatten()读取后注意维度顺序h5py 读出的数组通常需要转置特别是多通道时。我的习惯是把 v73 数据转成 float32再转成一维数组。整理程序里可以先用二进制读前 8 个字节判断版本自动选择loadmat还是h5py这样整个数据包就不会因为一个文件中断。5.2 标签错位文件名解析时的排序陷阱现象训练出来的混淆矩阵里内圈故障的样本被预测成外圈而且比例很均匀不像随机错误。原因批量读取时用glob(*.mat)返回的文件列表顺序和文件名自然排序不一致比如file10.mat排在file2.mat前面导致按文件顺序赋标签时错位。解决按文件名排序时使用自然排序不要用sorted(str)的字典序。用 Python 的natsort库pip install natsortfrom natsort import natsorted files natsorted(data_root.glob(*.mat))排序后打印一次文件名和对应标签映射表人工核对前 20 行。尤其是带6、3这类位置后缀的外圈故障文件名相似度很高最容易看漏。5.3 同源泄漏训练测试集划分后准确率虚高现象测试集准确率 99% 以上换成自己采集的轴承数据就只有 60%怀疑模型泛化能力差。原因切窗后随机划分数据集同一个 mat 文件的相邻窗口同时出现在训练集和测试集信息高度重合。振动信号是连续时序相邻窗口波形相似度可能超过 0.9测试集相当于背答案。解决严格按文件划分或者按不同的连续时间段划分。更稳妥的做法是每个 mat 文件切窗后把窗口按原始时间顺序分成三段每段分给不同集合从时间段层面避免泄漏。代码上就是上面 3.4 节里用GroupShuffleSplit并把group设为文件名索引。5.4 外圈故障的“静止载荷区”被切窗漏掉现象外圈故障分类准确率比内圈和滚动体低尤其在某些负载下外圈故障窗口混入正常样本。原因CWRU 外圈故障时如果滚动体经过非承载区冲击特征不明显而且外圈故障位置相对负载区固定有的 mat 文件里的信号包含大量冲击较弱的时间段。切窗后你不看波形分布就会把冲击少的窗口当正常。解决切窗外圈故障时先对整段信号做包络谱或均方根统计挑出冲击明显的区间再切窗。具体做法是按小窗口计算 RMS指数滑窗定位高能量段只在高能量段上切。这个策略能显著提升外圈故障的分类效果。如果你发现某个外圈文件切出的窗 RMS 分布有两个峰说明该文件混合了承载区和静止载荷区的信号建议把低能量峰的部分舍弃或者单独标注。6. 最后一步验证你的整理程序是否正确的一个小技巧用频谱校验整理完数据不要急着训模型。先用一个简单的方法验证标签和信号是否匹配——计算轴承故障特征频率看频谱峰值是否出现在理论位置。CWRU 数据有公开的轴承参数驱动端轴承节径约 1.537 英寸滚动体直径约 0.3125 英寸滚子数 9接触角 0。这些参数在官方文档里能查到用它们和转速算出内外圈特征频率和 FFT 谱峰值对照。以 1797 rpm 为例轴频约 29.95 Hz。外圈故障特征频率 BPFO 约 3.048 倍轴频也就是 91.2 Hz内圈故障 BPFI 约 5.048 倍轴频约 151 Hz。程序里可以这样验证单个窗口def verify_by_fft(data, fs, target_freq): spectrum np.fft.rfft(data) freqs np.fft.rfftfreq(len(data), 1/fs) peak_idx np.argmax(np.abs(spectrum[10:])) 10 peak_freq freqs[peak_idx] print(f峰值频率: {peak_freq:.2f} Hz, 理论: {target_freq:.2f} Hz)实际操作中故障特征频率不一定落在幅值最大处因为转速波动和转频谐波干扰所以更稳的是去看目标频率附近 3Hz 范围内有没有明显峰。如果内圈标签的窗口理论频率附近一点谱峰都没有那大概率是标签映射错了。这个验证过程不用跑模型几十秒就能在全部文件上扫一遍是整理程序的一个强保险。我自己每次整理完 CWRU 数据集都会先把每个故障类别的第一个窗口画出来做一次 RMS 和包络谱检查再跑 FFT 对照特征频率。这个习惯帮我避免过至少三次标签错位的返工。希望这个技巧对你有用也让你后续用 Python 折腾 CWRU 数据时少走一点弯路。本文还有配套的精品资源点击获取

关于本文作者

来自尧图内容编辑团队

尧图内容编辑团队 内容团队

尧图内容编辑团队

本文由尧图网络内容编辑团队执笔。团队由资深项目经理、前端工程师与设计师组成,所有内容均来自亲手交付的真实项目,先讲清问题、再给出可落地的解法。尧图深耕北京网站建设十年,服务过京华建材集团、智造科技等各行业客户,把一线经验沉淀为可复用的行业观察。

  • 十年建站经验,覆盖建材、制造、服务、文创等
  • 项目经理把关选题与事实准确性
  • 工程师与设计师联合撰写专业细节
  • 统一编辑规范,保证文风与排版一致
  • 每月复盘转化数据,迭代选题方向

延伸阅读

相关资讯与近期热门内容

深度阅读推荐

建站决策前值得细读的三篇

网站改版的5个关键决策
2024-08-12

网站改版的5个关键决策

什么时候该改版、改到什么程度、如何避免流量掉光,京华建材集团改版复盘给出答案。

获取专属建站方案

看完文章,把您的行业与预算告诉我们,免费获取一份量身定制的官网建设方案与报价。

立即免费咨询