
简介本资源为基于深度学习的故障检测算法完整项目源码包面向具备Python基础、希望将深度学习落地于工业设备预测性维护的开发者与研究人员。项目围绕传感器时序数据展开涵盖数据预处理、模型定义、训练脚本、验证测试与推理部署等环节可帮助读者理解CNN、RNN、LSTM等网络在故障识别中的实际用法。压缩包共491个文件以254个py源码与166个pyc编译文件为主另含30个log日志、若干xml配置及TensorBoard事件文件整体约1.19MB目录结构清晰便于按模块查阅。目前已有214人学习下载。通过该实践读者可掌握从特征自动提取、超参数调优到模型评估的完整流程并借助requirements.txt与README快速复现实验为构建生产环境下的故障检测系统提供可参考的工程范例。1. 拆开“基于深度学习的故障检测算法.zip”里面到底该有什么工业设备、旋转机械、电力变压器、化工流程这些场景每天都在产生振动、温度、电流、压力等时序数据。传统做法是设阈值、看频谱、人工巡检但工况一变、负载一波动误报和漏报就压不住。基于深度学习的故障检测算法要解决的就是把“人盯波形”变成“模型盯波形”让异常在早期就被揪出来。这个方向适合两类人一是手里有设备传感器数据、想上异常检测的工程师二是想找一个能跑通全流程的深度学习实战项目案例的学生或转行者。它不要求你从零发明网络结构但要求你把数据切窗、标签构造、模型选型、阈值设定这条链路走通。下面按“数据怎么进、模型怎么选、代码怎么写、坑怎么避”的顺序展开每一步都落到可复现的命令和参数上。2. 故障检测的数据管线从原始振动信号到模型能吃的张量2.1 先搞清楚你的故障检测属于哪一类任务故障检测在深度学习里通常落在三种任务形态上选错形态后面全白做。第一种是异常检测正常样本多、故障样本极少甚至没有目标是学正常分布偏离即报警。第二种是故障分类每种故障有标签目标是分清楚是轴承内圈还是外圈。第三种是剩余寿命预测输出还能跑多少小时。标题里写的是“故障检测算法”最常见、最稳妥的落地形态是异常检测加二分类因为工业现场故障标签往往不全。我一般会先问三个问题有没有故障标签故障样本占比多少数据是连续时序还是离散快照如果故障样本占比低于 5%直接上分类会严重偏斜这时候用自编码器重构误差或单类分类更稳。如果标签齐全且每类都有几百条以上那就走 CNN 或 LSTM 分类。这个判断决定了后面所有代码的走向不要跳过。2.2 滑动窗口切分把一维时序变成二维张量原始振动信号是一长条一维数组模型不能直接吃。常见做法是滑动窗口切分把连续 N 个采样点切成一个样本。窗口长度和步长是两个必调参数。窗口太短故障特征频率展不开窗口太长样本数骤减且引入无关工况。import numpy as np def sliding_window(signal, window_size1024, step512): signal: 一维振动信号数组 window_size: 每个样本的采样点数常用 512/1024/2048 step: 窗口滑动步长通常取 window_size 的一半做重叠 返回: shape(样本数, window_size) 的二维数组 samples [] for start in range(0, len(signal) - window_size 1, step): samples.append(signal[start:start window_size]) return np.array(samples) # 示例采样率 12kHz 的轴承振动信号 raw np.random.randn(120000) # 实际替换为你的数据 X sliding_window(raw, window_size1024, step512) print(X.shape) # (231, 1024)这段代码的逻辑很直白用固定长度窗口在信号上滑动每次取 1024 个点作为一个样本步长 512 意味着相邻样本有一半重叠能增加样本数量并平滑边界效应。参数上如果采样率是 12kHz1024 点对应约 85ms足以覆盖轴承故障特征频率的几个周期。步长取窗口一半是经验值样本太少时可以缩小到 256但要注意重叠过高会让训练集和验证集泄漏。2.3 标签构造与训练集划分的边界坑异常检测任务里标签构造比模型本身更容易翻车。常见做法是把正常数据标 0故障数据标 1。但工业数据往往有“退化期”设备从正常到故障是渐变的中间那段既不算正常也不算故障。我一般会把退化期样本直接丢弃或者单独标一个“预警”类避免模型学到模糊边界。划分训练集和测试集时绝对不能随机打乱后按比例切。时序数据有强自相关性随机切会让相邻窗口分别进入训练和测试造成数据泄漏测试指标虚高。正确做法是按时间顺序切前 70% 做训练后 30% 做测试。如果有多台设备按设备切分更严格。这个坑我见过太多次指标好看但上线就废血泪经验。3. 模型选型CNN、LSTM 还是自编码器别上来就堆 Transformer3.1 一维 CNN 做故障分类的最小可用结构对于有标签的故障分类一维 CNN 是性价比最高的起点。它参数量小、训练快、对局部冲击特征敏感正好匹配振动信号里轴承故障的周期性冲击。下面是一个能直接跑的最小结构。import torch import torch.nn as nn class FaultCNN(nn.Module): def __init__(self, num_classes4, input_len1024): super().__init__() self.features nn.Sequential( # 第一层大卷积核抓取低频冲击包络 nn.Conv1d(1, 16, kernel_size64, stride8, padding32), nn.BatchNorm1d(16), nn.ReLU(), nn.MaxPool1d(2), # 第二层小卷积核抓取高频细节 nn.Conv1d(16, 32, kernel_size16, stride2, padding8), nn.BatchNorm1d(32), nn.ReLU(), nn.MaxPool1d(2), nn.Conv1d(32, 64, kernel_size8, stride2, padding4), nn.BatchNorm1d(64), nn.ReLU(), nn.AdaptiveAvgPool1d(1) ) self.classifier nn.Linear(64, num_classes) def forward(self, x): # x: (batch, 1, input_len) x self.features(x) x x.squeeze(-1) return self.classifier(x) model FaultCNN(num_classes4) dummy torch.randn(8, 1, 1024) print(model(dummy).shape) # (8, 4)结构说明第一层用 kernel_size64、stride8 的大卷积核目的是快速降采样并捕获低频冲击包络这是振动信号里故障特征最明显的频段。后面两层逐步减小卷积核、增加通道数抓取更细的纹理。AdaptiveAvgPool1d(1) 把时间维压成 1避免全连接层参数爆炸。参数上num_classes 按你的故障类别数改input_len 必须和切窗长度一致。如果样本很少把通道数减半否则过拟合会非常快。3.2 自编码器做无监督异常检测重构误差怎么定阈值没有标签时自编码器是首选。思路是只用正常数据训练让模型学会压缩和还原正常信号故障信号因为没见过重构误差会明显变大。难点在于阈值怎么定定高了漏报定低了误报。class ConvAE(nn.Module): def __init__(self, input_len1024, latent32): super().__init__() self.encoder nn.Sequential( nn.Conv1d(1, 16, 7, stride2, padding3), nn.ReLU(), nn.Conv1d(16, 32, 7, stride2, padding3), nn.ReLU(), nn.AdaptiveAvgPool1d(latent) ) self.decoder nn.Sequential( nn.ConvTranspose1d(32, 16, 7, stride2, padding3, output_padding1), nn.ReLU(), nn.ConvTranspose1d(16, 1, 7, stride2, padding3, output_padding1), ) # 上采样回原始长度 self.upsample nn.Upsample(sizeinput_len, modelinear, align_cornersFalse) def forward(self, x): z self.encoder(x) out self.decoder(z) return self.upsample(out) # 阈值设定用正常验证集的重构误差均值 3 倍标准差 def compute_threshold(model, normal_loader, devicecpu): model.eval() errors [] with torch.no_grad(): for batch in normal_loader: batch batch.to(device) recon model(batch) # 每个样本的均方误差 err ((recon - batch) ** 2).mean(dim[1, 2]) errors.extend(err.cpu().numpy()) errors np.array(errors) return errors.mean() 3 * errors.std() threshold compute_threshold(model, normal_loader) print(f报警阈值: {threshold:.6f})逻辑上编码器把 1024 点信号压成 32 维潜向量解码器再还原。训练时只喂正常数据损失用 MSE。阈值用正常验证集误差的均值加三倍标准差这是工程上最常用的经验法则对应正态分布下约 99.7% 的正常样本不会被误报。如果现场误报还是多把倍数提到 4 或 5如果漏报严重降到 2。注意潜向量维度 latent 不要设太小32 到 64 之间比较稳太小会连正常信号都重构不好。3.3 LSTM 和 Transformer 在故障检测里的适用边界LSTM 适合故障是渐变累积的场景比如温度缓慢爬升、磨损逐渐加剧它能记住长时间依赖。但 LSTM 训练慢、调参玄学样本少于几千条时不建议用。Transformer 这两年很热但一维振动信号本身局部性强自注意力在样本量不够时容易过拟合我一般只在多传感器融合、序列很长且样本充足时才考虑。对于大多数“基于深度学习的故障检测算法”落地场景CNN 加自编码器组合已经能覆盖八成需求别为了追新而翻车。4. 训练、验证与部署把模型跑起来并接上报警4.1 训练循环里必须监控的三个量训练故障检测模型不能只看 loss。我一般同时盯三个量训练损失、验证损失、验证集上的报警误报率。前两个判断过拟合第三个判断实际可用性。下面是一个带早停和误报率计算的训练骨架。def train_one_epoch(model, loader, optimizer, criterion, device): model.train() total_loss 0 for x, y in loader: x, y x.to(device), y.to(device) optimizer.zero_grad() logits model(x) loss criterion(logits, y) loss.backward() optimizer.step() total_loss loss.item() * x.size(0) return total_loss / len(loader.dataset) def evaluate_false_alarm(model, normal_loader, threshold, device): 在正常验证集上算误报率 model.eval() false_alarms 0 total 0 with torch.no_grad(): for batch in normal_loader: batch batch.to(device) recon model(batch) err ((recon - batch) ** 2).mean(dim[1, 2]) false_alarms (err threshold).sum().item() total batch.size(0) return false_alarms / total # 训练主循环 for epoch in range(50): train_loss train_one_epoch(model, train_loader, optimizer, criterion, device) val_loss train_one_epoch(model, val_loader, optimizer, criterion, device) fa_rate evaluate_false_alarm(model, normal_val_loader, threshold, device) print(fEpoch {epoch}: train{train_loss:.4f} val{val_loss:.4f} 误报率{fa_rate:.4f}) if fa_rate 0.05: # 误报超过 5% 就停下来调阈值 break关键参数学习率用 1e-3 配 Adam 是安全起点batch_size 取 32 或 64。误报率超过 5% 时不要继续硬训先回头调阈值或检查正常验证集是否混入了退化期样本。早停耐心值设 5 到 10 个 epoch避免浪费算力。4.2 模型导出与推理接口的最小实现训练完要部署最常见的是导出 ONNX 或直接保存 state_dict 用 Flask/FastAPI 包一层。下面是把 PyTorch 模型导出 ONNX 的命令方便后续用 ONNX Runtime 在边缘设备上跑。import torch.onnx model.eval() dummy_input torch.randn(1, 1, 1024) torch.onnx.export( model, dummy_input, fault_detector.onnx, input_names[signal], output_names[logits], dynamic_axes{signal: {0: batch}, logits: {0: batch}}, opset_version13 ) print(导出完成: fault_detector.onnx)dynamic_axes 让 batch 维可变推理时一次可以送多条。opset_version 用 13 兼容性最好。导出后务必用 onnxruntime 跑一遍对比输出数值误差应在 1e-4 以内。如果边缘设备是 ARM 架构还要确认算子支持情况必要时把 AdaptiveAvgPool 换成固定尺寸的 AvgPool。4.3 报警策略连续多窗触发再报别单窗就喊单窗口重构误差超阈值就报警现场会炸锅。我一般用“连续 N 个窗口中有 M 个超阈值”才触发报警比如 5 个窗口里至少 3 个超限。这样能压掉大部分偶发冲击造成的误报。N 和 M 按你的采样步长和响应速度要求调步长 512、采样率 12kHz 时5 个窗口约 0.2 秒足够过滤瞬时干扰。这个策略不需要改模型只在推理后处理里加一个滑动计数器即可。5. 避坑与排查故障检测算法落地时最常翻车的五件事5.1 现象训练集准确率 99%上线后误报不断原因随机划分时序数据导致数据泄漏模型记住了训练样本的邻近片段测试集和训练集高度相似。解决严格按时间顺序切分训练集在前、测试集在后中间留一段缓冲丢弃。如果有多设备按设备切分。5.2 现象自编码器对正常数据重构误差也很大原因潜向量维度设得太小或者编码器下采样过猛正常信号的细节被压没了。解决把 latent 从 16 提到 32 或 64减少一层下采样检查输入是否做了归一化。振动信号幅值差异大不归一化会让模型偏向大幅值片段。5.3 现象故障分类模型把某类故障全预测成另一类原因类别不平衡少数类样本太少模型直接摆烂。解决用加权交叉熵权重按类别频率倒数设置或者对少数类做窗口重叠增强把样本数拉到同一量级。不要直接用 SMOTE 对时序信号插值会破坏物理特征。5.4 现象阈值在验证集上很好换一台设备就失效原因不同设备的振动幅值、噪声水平、安装方式不同模型和阈值都没有跨设备泛化能力。解决做归一化时用每台设备自身的均值和标准差而不是全局统计量阈值也按设备单独标定。更彻底的做法是训练时加入设备标签做域适应但工程上先做归一化就能救回大半。5.5 现象推理延迟太高边缘设备跑不动原因模型通道数太多或输入窗口太长。解决把窗口从 2048 降到 1024通道数减半用深度可分离卷积替换普通卷积。导出 ONNX 后用 onnxruntime 的量化工具做 INT8 量化速度能提 2 到 3 倍精度掉点通常在 1% 以内。6. 进阶技巧用频域特征和集成策略把误报再压一档时域波形对早期微弱故障不敏感我习惯在输入里并联一路频域特征。具体做法是对每个窗口做 FFT取幅值谱的前 256 个点和原始时域信号拼成双通道输入。这样 CNN 既能看波形冲击又能看特征频率有没有冒头。代码改动很小在数据加载时加一步 FFT 即可。def add_fft_channel(X): X: (样本数, window_size) - (样本数, 2, window_size) fft_mag np.abs(np.fft.rfft(X, axis1)) # 取前 window_size 个点不足补零 if fft_mag.shape[1] X.shape[1]: pad np.zeros((X.shape[0], X.shape[1] - fft_mag.shape[1])) fft_mag np.concatenate([fft_mag, pad], axis1) else: fft_mag fft_mag[:, :X.shape[1]] return np.stack([X, fft_mag], axis1) X_time np.random.randn(231, 1024) X_two_ch add_fft_channel(X_time) print(X_two_ch.shape) # (231, 2, 1024)模型第一层 Conv1d 的 in_channels 从 1 改成 2 就行。频域通道对轴承故障的特征频率特别敏感能比纯时域提前几十个窗口发现异常。另一个技巧是集成训练三个不同初始化的自编码器取重构误差的中位数作为最终分数。中位数比均值抗噪单个模型抽风不会直接触发报警。这两个改动加起来我在几个公开轴承数据集上把误报率从 8% 压到了 3% 左右代价是推理时间增加不到一倍。最后说个习惯每次调完阈值我都会把最近一周的正常数据回放一遍看误报次数能不能接受再决定要不要上线。模型指标再漂亮现场不认就是白搭。希望帮到你。本文还有配套的精品资源点击获取