工业设备故障检测数据集实战:从数据清洗到1D-CNN训练闭环
发布时间:2026/9/27 23:43:29来源:尧图网络
简介工业设备故障检测数据集面向工业视觉算法工程师、智能制造开发者及计算机视觉研究者聚焦设备预测性维护与异常定位任务。数据集覆盖腐蚀、软管磨损、活塞故障、受潮四类典型工业故障共752张真实工业场景实拍图像其中训练集591张、验证集161张均采用YOLO格式标注边界框与类别标签可直接接入YOLO系列等主流检测框架训练。压缩包共1506个文件以752个jpg图像与752个txt标注文件为主另含1个yaml数据配置和1份docx说明文档整体约36.09MB目录结构清晰便于快速划分训练与验证。目前已有232人学习下载。该资源可支撑故障预警系统开发、产线自动化质检、设备健康评估平台搭建及工业检测算法研究多角度、多状态的故障样本有助于提升模型泛化能力降低工业视觉应用落地成本。1. 工业设备故障检测数据集从压缩包到可训练样本的落地路径工业设备故障检测数据集.zip 这类资源真正的价值不在压缩包本身而在于它能不能被快速转成可训练、可复现的样本。很多做嵌入式工业设备监测的团队拿到数据后卡在三个地方采样率不统一、标签口径混乱、正常样本远多于故障样本。我见过一个风电齿轮箱项目原始数据 12GB清洗完只剩 3.2GB 可用故障片段不到 400 条。这篇笔记按「先看懂数据长什么样、再跑通最小训练、最后处理类别不平衡」的顺序展开适合做设备预测性维护、边缘端异常检测的工程师也适合刚接触工业时序数据、想用 YOLOv8 或时序模型做故障分类的读者。核心词工业设备、故障检测、数据集会在各章参数和脚本里反复出现不堆砌只讲能直接抄的步骤。2. 拆开压缩包先看三件事采样率、标签格式、通道数拿到工业设备故障检测数据集别急着写 DataLoader。先做一次结构盘点否则后面训练 loss 不降你连是数据问题还是模型问题都分不清。常见做法是解压后先跑一段统计脚本把每个文件的元信息打出来。2.1 用 Python 扫描目录并输出数据概况import os import numpy as np import pandas as pd DATA_ROOT ./industrial_fault_dataset records [] for root, dirs, files in os.walk(DATA_ROOT): for f in files: if f.endswith((.csv, .npy, .mat)): path os.path.join(root, f) size_kb os.path.getsize(path) / 1024 records.append({ file: f, dir: os.path.basename(root), size_kb: round(size_kb, 1), ext: os.path.splitext(f)[1] }) df pd.DataFrame(records) print(df.groupby([dir, ext]).agg( count(file, count), total_kb(size_kb, sum) ))这段脚本不依赖任何深度学习框架纯标准库加 pandas。DATA_ROOT指向解压后的根目录os.walk递归遍历所有子目录。输出按目录和扩展名分组能立刻看出哪类故障样本少、哪种格式占大头。如果某个类别只有个位数文件后面做分层采样时就要特别处理。2.2 采样率和通道数决定你用什么模型工业设备振动信号常见采样率是 12.8kHz、25.6kHz、51.2kHz电流信号常见 10kHz 或 20kHz。通道数从单轴加速度到三轴加温度共 4 通道都有。这两个参数直接决定预处理方式参数常见取值对建模的影响采样率12.8k / 25.6k / 51.2k Hz决定窗口长度12.8k 下 1024 点约 80ms通道数1 / 3 / 4单通道用 1D-CNN多通道可做早期融合标签粒度文件级 / 片段级片段级需要额外切窗文件级直接分类故障类型数3~12 类少于 5 类优先考虑异常检测而非多分类我一般会先读一个文件确认维度顺序。如果是.mat文件用scipy.io.loadmat看 key如果是.npy直接np.load看 shape。维度顺序搞反是血泪经验里最常见的一种翻车把通道当时间步模型训到天亮也不收敛。2.3 标签映射表要单独落盘工业设备故障检测数据集的标签经常藏在文件名或目录名里比如inner_race_0.3mm.csv、outer_race_0.5mm.csv。不要每次训练都现解析写一个label_map.json固定下来import json label_map { normal: 0, inner_race: 1, outer_race: 2, ball: 3, cage: 4 } with open(label_map.json, w, encodingutf-8) as f: json.dump(label_map, f, ensure_asciiFalse, indent2)参数说明key 是目录名或文件名中的故障关键词value 是训练时的整数标签。ensure_asciiFalse保证中文类别名可读。落盘后训练脚本、评估脚本、推理脚本共用同一份映射避免某次实验把 inner_race 和 outer_race 标反了还找不到原因。3. 从原始信号到训练样本切窗、归一化、转 YOLOv8 格式数据盘点完下一步是把它变成模型能吃的张量。工业时序故障检测和图像任务不同切窗策略、归一化方式、增强手段都会显著影响指标。这一章按「切窗 → 归一化 → 格式转换」三步走每步给可执行代码。3.1 滑动窗口切分与重叠率设置import numpy as np def sliding_window(signal, window_size1024, stride512): signal: shape (time_steps, channels) 返回: shape (num_windows, window_size, channels) windows [] for start in range(0, signal.shape[0] - window_size 1, stride): windows.append(signal[start:start window_size]) return np.stack(windows) raw np.load(./industrial_fault_dataset/inner_race/sample_001.npy) print(raw shape:, raw.shape) windows sliding_window(raw, window_size1024, stride512) print(windows shape:, windows.shape)window_size1024在 12.8kHz 采样率下对应 80ms覆盖一个冲击周期。stride512表示 50% 重叠既能增加样本量又不会让相邻窗口过于相似导致验证集泄漏。如果故障冲击间隔较长把 window_size 提到 2048 或 4096如果设备转速高、冲击密集1024 足够。注意训练集和验证集切窗时要按文件划分不能先切窗再随机分否则同一段信号会同时出现在两边。3.2 归一化选 Z-score 还是 Min-Max工业振动信号常有量纲差异三轴加速度和温度放一起不归一化模型会被大量纲通道主导。常见做法有两种Z-score(x - mean) / std适合近似高斯分布的振动信号对异常值敏感。Min-Max(x - min) / (max - min)适合幅值范围已知且稳定的场景。我一般用 Z-score但 mean 和 std 只从训练集算然后应用到验证集和测试集。下面这个类把统计量固定下来class ZScoreNormalizer: def __init__(self): self.mean None self.std None def fit(self, X): self.mean X.mean(axis(0, 1), keepdimsTrue) self.std X.std(axis(0, 1), keepdimsTrue) 1e-8 def transform(self, X): return (X - self.mean) / self.stdaxis(0,1)表示在时间步和窗口两个维度上统计保留通道维度。1e-8防止除零。fit 只在训练集调用一次transform 用于所有集合。这个细节不做验证集指标会虚高上线后直接翻车。3.3 转成 YOLOv8 可用的图像或保持 1D 序列如果你的方案是 YOLOv8 做故障检测需要把一维信号转成时频图。常见做法是短时傅里叶变换或连续小波变换存成 PNG 再按 YOLO 格式标注。如果做纯时序分类保持 1D 序列用 1D-CNN 或 Transformer 更直接。两条路线的数据组织不同路线输入格式标注文件适用场景YOLOv8 图像PNG 时频图.txt 每行 class x y w h故障区域定位1D 序列分类.npy 数组label_map.json整段信号分类多模态数据集图像序列各自标注振动温度电流融合转 YOLOv8 格式时时频图尺寸建议 640x640类别数就是故障类型数。标注框可以整图覆盖也可以只标冲击区域。整图覆盖实现简单适合先跑通流程冲击区域标注需要额外做峰值检测适合对定位有要求的场景。4. 类别不平衡与跨设备泛化故障检测数据集的两个硬骨头工业设备故障检测数据集几乎不可能类别平衡。正常样本占 90% 以上是常态少数故障类只有几十条。另外同一型号不同设备之间的信号分布也有差异实验室数据训的模型搬到现场经常掉点。这一章讲怎么处理这两个问题。4.1 重采样、加权损失与异常检测的选型面对不平衡有三条路重采样对少数类过采样或对多数类欠采样。简单但容易过拟合少数类。加权损失在 CrossEntropyLoss 里传weight让少数类梯度更大。异常检测只学正常样本分布故障作为异常输出。适合故障样本极少的情况。我一般先试加权损失代码改动最小import torch import torch.nn as nn from collections import Counter labels [0] * 900 [1] * 60 [2] * 40 # 模拟分布 counts Counter(labels) total sum(counts.values()) weights [total / (len(counts) * counts[i]) for i in range(len(counts))] weights torch.tensor(weights, dtypetorch.float32) criterion nn.CrossEntropyLoss(weightweights) print(class weights:, weights)weights与类别频率成反比少数类权重更高。参数说明len(counts)是类别数counts[i]是第 i 类样本数。如果某类权重超过 50说明该类样本太少考虑合并或改用异常检测。加权损失不是万能药权重过大时模型会把正常样本误判为故障精确率下降。4.2 跨设备泛化的三个实用手段实验室到现场的泛化问题常见手段有归一化统计量按设备单独计算而不是全局统一。训练时加入设备维度的对抗损失让特征与设备无关。用少量目标设备数据做微调哪怕每类只有 10 条。我一般会留一个「目标域验证集」从现场采几段正常和故障数据不参与训练只用来观察泛化差距。如果目标域准确率比源域低 20 个点以上说明分布偏移严重需要做域适应。这个验证集不需要大每类 20 到 50 个窗口就能看出趋势。4.3 数据增强在时序信号里的边界时序增强和图像增强不同不能随便旋转裁剪。可用的手段包括加高斯噪声信噪比控制在 20dB 以上再低会破坏故障特征。时间偏移整体平移几个时间步模拟触发延迟。幅值缩放0.9 到 1.1 倍模拟负载波动。通道丢弃多通道时随机丢一个通道提升鲁棒性。注意不要用时间反转振动信号反转后物理意义改变。也不要用太大的幅值缩放故障冲击的幅值本身是重要特征。增强只加在训练集验证集和测试集保持原始分布。5. 避坑与排查工业设备故障检测数据集最常见的五个翻车点这一章按「现象 → 原因 → 解决」写都是实际项目里踩过的。5.1 训练 loss 不降准确率卡在多数类现象模型输出全是正常类准确率等于正常样本占比。原因类别极度不平衡模型学到「全猜正常」就能拿高准确率。解决先看混淆矩阵确认少数类是否全错然后加类别权重或改用 Focal Loss同时把评估指标从准确率换成 macro-F1 或召回率。5.2 验证集指标很高上线后误报频繁现象验证集 F1 0.95现场误报率超过 30%。原因验证集和训练集来自同一批文件切窗时重叠导致泄漏。解决按文件或按时间段划分数据集确保同一段信号不出现在两个集合。切窗的重叠只用于训练集内部扩充不跨集合。5.3 不同文件采样率不一致模型输入维度对不上现象DataLoader 报 shape mismatch或者训练时 loss 突然变 NaN。原因部分文件采样率是 25.6kHz部分是 12.8kHz切窗后长度不同。解决先统一重采样到同一频率用scipy.signal.resample或librosa.resample。重采样后再切窗并在元数据里记录原始采样率。5.4 标签映射顺序变了模型输出对不上类别名现象推理结果类别名和实际故障类型错位。原因训练时 label_map 是 A 顺序推理时重新生成成了 B 顺序。解决label_map.json 只生成一次训练和推理都从同一文件读取。如果必须改重新训练模型不要只改推理脚本。5.5 归一化统计量用了全量数据测试集信息泄漏现象测试集指标异常好换一批数据就崩。原因归一化时用了包含测试集的全部数据算 mean 和 std。解决统计量只在训练集 fit验证集和测试集只 transform。这个坑很隐蔽因为代码能跑通指标也好看但上线就暴露。6. 用 1D-CNN 跑通最小闭环从 .npy 到混淆矩阵前面把数据和坑都过了一遍这一章给一个能直接跑的最小训练脚本用 1D-CNN 做故障分类输出混淆矩阵。模型不大CPU 也能跑适合先验证数据管线是否通畅。import numpy as np import torch import torch.nn as nn from torch.utils.data import Dataset, DataLoader from sklearn.metrics import confusion_matrix import seaborn as sns import matplotlib.pyplot as plt class FaultDataset(Dataset): def __init__(self, windows, labels): self.X torch.tensor(windows, dtypetorch.float32).permute(0, 2, 1) self.y torch.tensor(labels, dtypetorch.long) def __len__(self): return len(self.y) def __getitem__(self, idx): return self.X[idx], self.y[idx] class CNN1D(nn.Module): def __init__(self, in_channels, num_classes): super().__init__() self.net nn.Sequential( nn.Conv1d(in_channels, 32, kernel_size7, padding3), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(32, 64, kernel_size5, padding2), nn.BatchNorm1d(64), nn.ReLU(), nn.AdaptiveAvgPool1d(1), nn.Flatten(), nn.Linear(64, num_classes) ) def forward(self, x): return self.net(x) # 假设 windows 和 labels 已按第 3 章流程准备好 train_ds FaultDataset(train_windows, train_labels) val_ds FaultDataset(val_windows, val_labels) train_loader DataLoader(train_ds, batch_size64, shuffleTrue) val_loader DataLoader(val_ds, batch_size64) model CNN1D(in_channelstrain_windows.shape[2], num_classes5) optimizer torch.optim.Adam(model.parameters(), lr1e-3) criterion nn.CrossEntropyLoss() for epoch in range(30): model.train() for x, y in train_loader: optimizer.zero_grad() loss criterion(model(x), y) loss.backward() optimizer.step() model.eval() preds, trues [], [] with torch.no_grad(): for x, y in val_loader: preds.extend(model(x).argmax(1).tolist()) trues.extend(y.tolist()) cm confusion_matrix(trues, preds) sns.heatmap(cm, annotTrue, fmtd, cmapBlues) plt.xlabel(Predicted) plt.ylabel(True) plt.savefig(confusion_matrix.png, dpi150)参数说明in_channels是通道数单轴振动填 1三轴填 3。kernel_size7对应约 0.5ms 的局部模式适合捕捉冲击。AdaptiveAvgPool1d(1)把时间维压成 1避免全连接层参数过多。学习率 1e-3 是 Adam 的常用起点如果 loss 震荡降到 5e-4。batch_size 64 在几千个窗口的数据集上比较稳。跑完看混淆矩阵重点看少数类是否被完全忽略。如果某个故障类召回率为 0回到第 4 章加权重或过采样。如果所有类都还行但整体偏低检查归一化和切窗参数。这个闭环跑通后再换更复杂的模型或加多模态数据才有意义。我自己的习惯是任何工业设备故障检测数据集先跑通 1D-CNN 加混淆矩阵再谈 Transformer 或 YOLOv8。数据管线不通模型再新也是黑匣子。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网