
设备非计划停机这件事做工厂的人都知道有多疼。产线一停损失按分钟算维修工单满天飞备件库里翻不到对应型号等备件到货停机时间已经按天计了。所以这几年预测性维护这个词从论文走进了车间大家都想赶在设备真正坏掉之前拿到预警。但真正落地起来项目失败率并不低要么数据采了一堆用不上要么模型在实验室里准确率好看、一上产线就失灵。这篇内容我结合自己做过的一个实际项目聊聊怎么用开源的 MyEMS 平台把设备数据打通再通过 CNN-LSTM 神经网络模型把故障预警准确率做到 92%。整个过程包含数据链路怎么搭、模型结构怎么选、标签怎么定义、阈值怎么调以及那些踩过之后才发现的水坑。如果你们团队正准备上预测性维护或者已经在做但准确率始终卡在 80% 上下这篇内容应该能给你几张能直接用的图纸。1. 设备故障预警的数据地基MyEMS 在预测性维护里到底扮演什么角色1.1 MyEMS 不只是能源管理平台它还是预测性维护的数据中台很多团队一提到预测性维护第一反应是先买振动传感器、先搭数据采集网关结果项目一开始就被硬件选型和数据接入困住了。MyEMS 作为一套成熟的能源管理平台本身的目标是能耗监测与分析但它的数据架构决定了它完全可以承担预测性维护的数据基座职责。MyEMS 的底层数据采集支持 Modbus TCP/RTU、OPC UA、BACnet、MQTT 这几种工业场景最常见、也最皮实的协议。这意味着它不只是能接电表、水表、气表这类能源计量设备它同样能接 PLC、DCS 服务器、带网关的振动传感器、温度传感器、电流互感器。在实战中我的做法是把设备端的电流、电压、有功功率、绕组温度、轴承振动有效值这五类信号统一汇聚到 MyEMS利用它自带的数据采集器定时轮询或者订阅推送把高频信号落到数据库里。这里有个关键点MyEMS 默认偏向分钟级采集频率但预测性维护往往需要在秒级甚至毫秒级信号上做分析。我的处理方案是在 MyEMS 之外增加一条旁路高频采集通道低频数据如每分钟的平均功率、累计运行时长、启停状态直接走 MyEMS高频信号如振动原始波形、电流瞬态波形走独立的时序数据库如 InfluxDB再按时间戳对齐合并。这样既保留了 MyEMS 的稳定调度、告警和可视化能力又不会让高频信号把 MySQL/MongoDB 拖垮。数据链路的具体构成如下MyEMS 采集器对接 Modbus TCP 网关轮询电参数和温度周期 1 分钟振动采集网关通过边缘计算输出 RMS 值有效值、峰值、峭度指标每 1 秒推送一次 MQTTMyEMS 告警引擎对越限参数温度80℃、电流超额定值 15%做基础越限报警数据合并层按设备 ID 和 10 秒时间窗口对齐生成一张宽表供特征工程和模型训练使用这样的分层逻辑本质上把人力和算力放在了最关键的环节——不是纠结于某一种传感器或者某一条协议而是先把哪些数据真正反映了设备健康状态这个问题想清楚再决定采集架构。1.2 数据清洗与对齐预测性维护的最后一公里从 MyEMS 拉出来的数据一般不会直接变成训练样本。首先是数据质量问题工业现场的传感器偶发断线、通信拥塞、网关重启都会造成某一时间段数据的缺失或者跳变。刚开始我用的是线性插值填充缺失值后来发现振动信号这种高度非平稳的数据线性插值会引入明显的人为突变模型错误地把这些插值段识别成了异常特征导致误报率飙升。更好的方案是分字段处理温度、功率这类缓变信号使用前后 5 分钟的均值填充振动 RMS 信号不填充直接标记该时间窗口为不可用在样本生成时剔除电流瞬态波形的异常尖峰使用 3σ 原则剔除而不是强行平滑数据对齐是另一个容易被低估的问题。MyEMS 的分钟级数据和振动网关的秒级数据在时间戳上天然是错开的。如果直接做内连接你会发现每个分钟点上只有一条振动记录大量信息被浪费了。我在实践中把振动数据按秒求平均和最大值再用 resample 的方式对齐到分钟级生成分钟级宽表。这样既保留了振动信号的趋势特征又解决了数据频率不一致的问题。数据清洗完成后才算真正进入模型构建阶段。这一步我自己的体会是在数据工程上花的每一分钟都会在模型准确率上得到回报。跳过数据清洗直接灌模型后面调参调到头秃都不一定能把准确率拉回来。2. 为什么单用 LSTM 不够CNN 和 LSTM 的职责划分2.1 设备故障信号的两个核心特征局部波形异常与长期退化趋势纯 LSTM 模型的强项是捕捉时间序列的前后依赖关系这在预测性维护场景中很重要因为设备从健康到失效通常是一个渐变过程。但实际故障信号不是只有渐变这一面。我处理过的一台离心泵案例里轴承早期故障会在振动信号中产生周期性的冲击脉冲这种冲击在时域波形上表现为数毫秒内幅值剧烈变化在频谱上则显示出边频带。这种局部波形特征单靠 LSTM 很难捕获因为 LSTM 天然适合处理全局时序规律对局部高频模式不够敏感。CNN卷积神经网络正好补上这个短板。一维卷积核在时序信号上滑动本质上是做局部模式匹配。一个卷积核可以学会识别突发的冲击脉冲另一个卷积核可以学会识别持续上升的基线漂移。多个卷积核的输出再交给 LSTM模型就有了先用局部特征筛一遍再从时间维度看这些特征怎么演化的能力。2.2 模型结构一维卷积提取局部特征LSTM 学习退化节奏我的 CNN-LSTM 模型结构并不是所有实验里都相同但最终取得 92% 准确率的版本结构如下输入层形状为(时间步长60, 特征数8)的滑动窗口窗口覆盖 10 分钟的运行数据第一层 1D CNN64 个滤波器卷积核大小为 5激活函数 ReLU后面接 MaxPooling 层池化大小为 2第二层 1D CNN32 个滤波器卷积核大小为 3激活函数 ReLU后面再接一个 MaxPooling 层LSTM 层隐藏单元数为 64return_sequencesFalseDropout 设置为 0.3全连接层32 个神经元ReLU 激活再接 Dropout 0.2输出层1 个神经元Sigmoid 激活用于二分类正常/故障CNN 部分的意思可以这样理解第一个卷积层看短时间内的局部波形特征比如振动突然增大、电流波动异常第二个卷积层在前者的基础上看更抽象的组合特征比如振动增大的同时功率也在爬升。两个卷积层配合池化把输入从 60 个时间点压缩成更紧凑的特征序列再交给 LSTM 学习这 10 分钟里设备状态的整体演化路径。训练参数的选择上优化器用 Adam学习率初始值 0.001损失函数用 binary_crossentropy。批大小设为 32。整体参数量在 10 万级别单卡 GPU 训练 50 个 epoch 大约只需要几分钟工业场景的规模完全跑得动。2.3 输入张量形状与数据组织让模型看对东西模型输入的数据组织是整个实验中最容易出问题、也最容易被忽略的环节。很多团队的失败不是模型不行而是喂给模型的数据组织方式不合理。输入张量要求形状为(样本数, 时间步长, 特征数)。在特征选择上我用了 8 个特征电压有效值电流有效值有功功率绕组温度振动 RMS振动峰值峭度指标运行状态编码1运行0停机时间步长我设为 60含义是每个样本包含连续 60 个采样点。由于宽表是分钟级的60 个采样点就是 1 小时如果后续把采样频率提升到 10 秒一条那 60 步就意味着 10 分钟。窗口长度需要根据具体设备的时间常数来确定。我的调试经验是对于轴承类故障窗口太短小于 30 步模型学不到退化趋势太长大于 300 步则会引入过多历史无关信息导致模型对最近状态不敏感。你可以先做一个窗口长度扫描实验在验证集上对比 30/60/120/240 四档的准确率和召回率通常中间两档表现更好。3. 数据预处理与特征工程92% 准确率的一半功劳在这里3.1 样本不均衡问题健康样本比故障样本多得多工业场景的正常运行时间占绝大多数故障样本天然稀少。我曾经用一个月的连续运行数据做实验健康样本和故障样本的比例大约是 955。如果直接用这个数据集训练模型会走捷径——把所有样本都预测为健康整体准确率也能轻松达到 95%但这样的模型完全没有预警能力。解决不均衡问题我的方案组合了三种手段数据增强对故障样本做时间轴上的小幅度位移、加轻微高斯噪声扩增 2 倍类别权重在损失函数中加大故障类别的权重比如设置 class_weight{0:1, 1:5}让模型在训练时更重视故障样本的判别错误滑动窗口重叠采样在故障段前后各多取 20% 的重叠窗口让模型有更多机会看到故障快要发生和刚开始发生的过渡段这里要特别提醒一点数据增强不要破坏时序的因果性。工业时序数据和图像不一样平移和加噪要控制在合理幅度内如果噪声幅度过大模型会把噪声本身当作故障特征在真实场景中反而更加误报。3.2 标签定义故障不是坏了才叫故障预测性维护里的标签是决定项目成败的关键。工程上常犯的错误是拿故障停机时刻作为唯一的标签标注点然后让模型去学习停机前一刻的信号。这样做模型也能学到点东西但它的本质变成了故障分类而不是故障预警。我采用的标签策略是把故障发生前 30 分钟内的样本全部标记为正类即将故障。模型学出来的含义是这台设备在往后 30 分钟内可能会故障而不是这台设备当前已经故障。实际生产中30 分钟足够操作员做出响应也足够触发自动停机逻辑避免事故扩大。标签窗口的具体选择取决于故障的演化速度。对于轴承磨损这类慢变故障故障前 1 小时的信号往往已经有明显趋势建议标签窗口设长一点对于电机堵转这类突变故障标签窗口设 5-10 分钟就够了。你可以用故障前不同提前量分别构建标签对比模型的精确率和召回率曲线选择一个既不过早误报太多也不过晚来不及响应的提前期。3.3 数据标准化不要让温度特征的主导性淹没振动特征标准化策略上我踩过一个很典型的坑。一开始我直接用 sklearn 的 StandardScaler 对整个数据集做标准化模型在验证集上表现不错但一上线就失灵。后来排查发现问题出在温度特征和振动特征的量纲差异巨大温度范围 20-80℃振动 RMS 范围 0.1-10mm/s在模型训练时温度特征天然主导了梯度更新方向振动特征的作用被严重稀释了。正确的做法是先按时间序列切分数据集训练集/验证集/测试集然后在训练集上分别对每个特征计算均值和标准差再将这些统计量应用到验证集和测试集。也就是说绝对不能在划分数据集之前就对所有数据做标准化否则训练集偷看了测试集的信息这属于数据泄漏会虚高模型的评估指标。在部署阶段同样用训练集算好的统计量去标准化实时数据别用实时数据的滚动均值代替。4. 训练过程中的关键坑点与调参记录4.1 时间序列的数据切分绝对不能随机打乱时序数据最经典的数据泄漏方式就是随机划分训练集和测试集。如果一个滑动窗口来自第 10 天另一个滑动窗口来自第 12 天两者有大量时间重叠模型在训练时本质上已经见过测试数据的特征分布。这样验证集上的准确率会虚高但模型真实泛化能力要打折扣。我在实验中严格按时间顺序切分前 70% 的数据用于训练中间 15% 用于验证调整超参数最后 15% 用于测试只评估一次。这里有一个额外的好处这种切分方式更贴近上线后的实时推理场景——训练时用的是历史数据推理时面对的是未来真正没见过的数据点。4.2 早停与学习率衰减避免过拟合到血脉里工业数据集的故障样本数量本来就少模型很容易在训练集上过拟合。我在训练过程中使用了两道防线。第一道防线是早停EarlyStopping当验证集损失连续 8 个 epoch 不下降时停止训练并恢复到验证集损失最小的权重。第二道防线是学习率衰减使用 ReduceLROnPlateau 调度器当验证集损失连续 3 个 epoch 不下降时学习率乘以 0.5。这样在训练后期模型参数更新步长变小能够更精细地收敛到最优区域同时避免在最优解附近来回震荡。4.3 模型评估指标的解读准确率 92% 是怎么算出来的标题里说的 92% 准确率我在这里把算法交代清楚。准确率 (正确预测的样本数) / (总样本数)。需要注意的是在样本不均衡的背景下准确率可能具有欺骗性。我在模型评估时额外关注精确率Precision和召回率Recall精确率模型预测即将故障的样本中真正发生故障的比例召回率真实发生故障的样本中被模型提前捕捉到的比例最终模型的测试集结果如下指标数值准确率92.1%精确率84.6%召回率87.3%F1 分数85.9%如果只看准确率92% 看起来已经挺高了。但结合精确率和召回率看84.6% 的精确率意味着模型每发出约 100 次预警会有大约 15 次是误报。这个误报水平需要结合现场反馈来看对于一般工厂15% 的误报率会导致操作员对预警逐渐麻木最终模型失效因此我在后面的步骤中增加了误报抑制策略。5. 预警落地的最后一步阈值调整与部署推理5.1 不只是 0/1用概率输出配合动态阈值模型输出的不是最终的 0 或 1而是故障概率的连续值0-1 之间。很多团队直接把 0.5 作为分类阈值但实际效果不好。原因在于0.5 阈值是针对平衡数据集设计的工业场景中故障样本远少于健康样本最佳阈值往往低于 0.5。我用验证集绘制了精确率-召回率曲线PR 曲线找到在曲线拐角处使 F1 分数最大的阈值。在我的实验里最优阈值是 0.37而不是 0.5。意味着当模型输出的故障概率超过 0.37 时就发出预警。下调阈值会获取更高召回率但同时会引入更多误报。实际操作中我还加了迟滞区间设计概率超过高阈值如 0.6直接报警在低阈值如 0.3和高阈值之间连续触发 3 个时间窗口才报警。这种设计可以有效过滤掉偶发的信号毛刺同时不损失真正的早期故障信号。5.2 在线推理与结果可视化MyEMS 告警页面如何联动模型训练完成后部署方式没有选择重量级的训练服务器而是一个轻量推理服务。具体流程如下新到的数据实时写入 MyEMS 历史数据库并同步一份到 Redis 缓存保留最近 10 分钟推理服务每隔 1 分钟从 Redis 拉取最近 60 条有效采样点按训练阶段保存的特征统计量做标准化拼装成形状为(1, 60, 8)的张量送入 CNN-LSTM 模型模型输出故障概率经迟滞判断后写入结果表第 5 步的结果会同步写回 MyEMS 的告警记录表。MyEMS 的告警引擎一旦检测到自定义字段更新就能触发邮件、企业微信或者短信通知。配置方式是在 MyEMS 的告警规则里新增一条数据源指向推理服务输出的故障概率字段设置阈值条件即可。这样做的好处是操作员不需要切换到机器学习平台直接在原有的 MyEMS 界面上就能看到设备健康状态和报警信息。5.3 回旋镖效应模型上线后要做的闭环迭代模型部署上线不是终点。你可能会在短期内收到大量现场反馈说你们这个模型又在乱报了。这不是模型的问题而是反馈闭环没有建立起来。在工业场景中设备故障的标注永远是不够完整的有些故障发生后维修人员没有详细记录有些故障被避免了但没人意识到是预警的功劳。所以模型需要一版一版地持续迭代每一次设备停机、每一次维修工单、每一次预警响应都要重新整理成标签回灌到训练数据里。我的建议是每个月做一次模型重训练用最近两个月的数据 全部历史故障案例。另外把每次预警结果做成一个可以快速检索的列表让设备工程师标注真预警还是误报。这些标注数据是模型迭代提升的金矿比任何调参手段都有效。5.4 代码参考PyTorch 实现的核心训练流程最后放一段精简版的 PyTorch 训练代码方便复现。这不是完整工程代码但核心逻辑都能跑通你可以在此基础上扩展成完整的训练流水线。import torch import torch.nn as nn import numpy as np from torch.utils.data import DataLoader, TensorDataset class CNNLSTM(nn.Module): def __init__(self, n_features, n_hidden64, n_filters[64, 32], kernel_size[5, 3], dropout0.3): super(CNNLSTM, self).__init__() self.conv1 nn.Conv1d(n_features, n_filters[0], kernel_size[0], padding2) self.conv2 nn.Conv1d(n_filters[0], n_filters[1], kernel_size[1], padding1) self.pool nn.MaxPool1d(2) self.lstm nn.LSTM(n_filters[1], n_hidden, batch_firstTrue) self.fc1 nn.Linear(n_hidden, 32) self.fc2 nn.Linear(32, 1) self.dropout nn.Dropout(dropout) self.relu nn.ReLU() def forward(self, x): # x: (batch, seq_len, features) x x.permute(0, 2, 1) # 转成 (batch, features, seq_len) x self.pool(self.relu(self.conv1(x))) x self.pool(self.relu(self.conv2(x))) x x.permute(0, 2, 1) # 转回 (batch, seq_len, channels) out, _ self.lstm(x) out out[:, -1, :] # 取最后一个时间步的输出 out self.relu(self.fc1(out)) out self.dropout(out) out torch.sigmoid(self.fc2(out)) return out # 数据加载示意 # X_train: (num_samples, 60, 8) # y_train: (num_samples, 1) train_dataset TensorDataset(torch.tensor(X_train, dtypetorch.float32), torch.tensor(y_train, dtypetorch.float32)) train_loader DataLoader(train_dataset, batch_size32, shuffleTrue)训练循环不再展开但要注意shuffle 只在每个 epoch 内部的训练集上做验证集和测试集的 loader 一定要设置 shuffleFalse保证评估时的顺序性和时间完整性。6. 回到实际项目这套方案在什么场景下最划算6.1 最适合的应用对象旋转设备与关键工艺设备CNN-LSTM 这套模型不是对什么设备都管用。根据我的实践最适合的对象是长期连续运行的旋转设备电机、水泵、风机、压缩机、减速机和核心工艺设备如注塑机、空压机、制冷机组。这类设备的特点是工况相对稳定、传感器容易加装、故障模式有前兆振动上升、电流偏移、温度爬升。对于启动/停止极其频繁的非连续设备比如某些机器人工作站每次启停过程都会产生剧烈的电流和振动瞬变模型容易误识别为异常效果会打折扣。如果非要在这种情况下使用建议增加一个工况识别模块把模型只应用于稳定运行段或者针对启停瞬间单独建模。6.2 数据量与采集成本的最低门槛很多团队问要积累多久的数据才能开始做预测性维护我的答案是至少需要包含一次完整的设备故障历史和你期望覆盖的预警提前期。比如预警提前期是 30 分钟那从故障前 30 分钟到故障停机之间的数据段就是最宝贵的训练素材。如果你想覆盖多种故障模式那每一种模式都至少要有一到两次完整事件否则模型会有严重的偏科问题。在投入产出比方面这套方案比较适合设备单台价值高、停机损失大或者设备数量多、人工巡检难以覆盖全部关键点。如果一台设备的年维护成本很低那上一整套预测性维护系统的成本可能比设备本身还贵经济上不划算。6.3 数据安全与部署边界预测性维护永远只是辅助决策最后我想提一个容易在项目中失控的问题模型预警后到底要不要设置自动停机就我的经验而言除非是对安全有极强要求的场景如某些化工工艺否则不要轻易把模型输出直接接到自动停机逻辑上。模型有误差传感器有误报网络有延迟任何一环出错都可能造成比设备故障本身更大的生产损失。把预测性维护定位为辅助决策工具让预警信息辅助维修计划和备件调度是更稳妥、也更容易得到现场工程师信任的落地方式。在实际操作中我还见过不少团队试图把模型调到100% 准确这是不现实的。工业信号本身充满了噪声和不确定性92% 的预警准确率已经能带来显著价值。剩下的精力应该放在如何让操作员高效地处理那 8% 的误报以及如何通过闭环迭代不断提升整体系统的可靠度上。