
我做了三年的设备数据分析和预测性维护中间踩过不少坑也积累了一些真正能用的经验。这次分享的是一个已经落地运行了八个多月的项目——基于 MyEMS 平台用 CNN-LSTM 组合模型对车间关键机组做故障预警最终在真实生产数据上把预警准确率稳定在了 92% 左右。方案不复杂但很多细节是踩坑踩出来的从数据清洗到模型部署每一步都有值得复盘的地方。不管你是刚接触预测性维护还是已经在做设备数据分析但效果不理想这篇内容应该都能给你一些实质性的参考。1. 项目背景与方案选型思考1.1 设备突发故障为什么难防工厂里最怕的不是设备老化而是设备毫无预兆地趴窝。我参与维护的产线上有几台核心机组一旦停机直接影响整个班次的产出。过去靠的是定期保养加人工巡检但问题很明显定期保养是按固定周期做的设备实际状态可能早就不行了人工巡检依赖老师傅的经验听声音、摸温度主观性很强很难量化。我们统计过历史故障记录突发性故障占了接近七成而且从异常萌发到真正停机留给人的反应时间往往只有几个小时。这个窗口期如果能抓住就能避免非计划停机抓不住就是一次被动的抢修备件、人工、停产损失全都得买单。所以这个项目的核心目标很直接提前一小时以上预警设备即将发生的故障给现场人员留出处置时间。这不是要做花哨的数字孪生而是要解决一个非常实际的生产保障问题。1.2 为什么选 CNN-LSTM 组合模型模型选型我纠结了挺长时间。一开始试过单纯的 LSTM也试过传统的机器学习方法比如随机森林、XGBoost效果都差强人意。后来转向 CNN-LSTM 组合才算是找到了一个比较顺手的方案。先说说为什么单用 LSTM 不够理想。LSTM 擅长捕捉时间序列上的长期依赖关系但工业设备的传感器数据往往包含大量的局部特征也就是短时间窗口内信号形态的变化。比如振动信号在故障萌发期会出现高频冲击成分电流信号会出现微小的波形畸变。LSTM 在处理这种局部模式时效率不高它更擅长处理整个序列的趋势性变化。而 CNN卷积神经网络恰好擅长提取局部特征。一维卷积可以像滑动窗口一样在时间序列上扫描自动捕捉波形中的尖峰、畸变、周期性变化等局部模式。把 CNN 和 LSTM 串联起来等于先让卷积层做一遍特征提取把原始信号中的关键局部特征抠出来再把这些特征序列交给 LSTM 去建模时间上的依赖关系。这个先局部后全局的思路非常契合工业设备故障信号的特点。再说说为什么不走传统机器学习路线。随机森林和 XGBoost 我也做了一轮对比它们需要人工构造大量特征比如时域特征均值、峰值、峭度、频域特征频谱能量分布等等。但特征工程是个无底洞不同设备的故障模式差异很大特征的选择和组合非常耗时而且很难覆盖到所有故障形态。CNN-LSTM 是端到端学习原始时序数据进去故障概率出来中间的特征提取交给模型自己完成省去了大量人工特征工程的工作。1.3 MyEMS 在方案里的角色MyEMS 是一套开源的能源管理系统很多工厂都在用它采集电表、水表、气表的数据也支持设备运行状态的监控。选择 MyEMS 作为数据底座主要看中两点。第一它已经具备比较完善的数据采集链路。MyEMS 支持 Modbus、M-bus、BACnet、OPC-UA 等多种工业协议可以直接从 PLC、传感器、智能仪表中采集数据省去了我从零搭建数据采集层的功夫。第二它自带的一些基础告警机制可以作为兜底。我们的 AI 模型负责预测性预警但 MyEMS 原有的阈值告警依然保留形成了预测为主、规则兜底的双保险机制。关于 MyEMS 的具体部署细节我后面讲模型集成的时候会展开说明。这里想强调的核心思路是预测性维护不是要从零搭建一套全新的系统而是尽量复用已有的数据采集和监控能力把 AI 模型作为一个增量模块嵌进去。这样既降低了落地成本也更容易被现场人员接受。2. 数据工程预测性维护真正的地基模型选型再先进数据不行也是白搭。这个项目里花在数据准备上的时间比建模和训练加起来还要多得多。数据工程的每个环节都决定模型的上限。2.1 数据采集、清洗与对齐MyEMS 里存的数据主要是能耗数据但对于设备故障预测只有能耗数据远远不够。我们额外接了振动传感器和温度传感器振动频率设置为 10 分钟一个采样点温度和电流电压则是 1 分钟一个采样点。因为采样频率不一致数据对齐就成了第一个要解决的问题。这里说一下我的处理方法。MyEMS 底层用的是 MySQL 数据库我写了一个定时任务每隔 5 分钟把最近一段时间的数据从原始表里捞出来统一重采样到 1 分钟的频率。振动数据因为原始采样颗粒度是 10 分钟就采用前向填充把每 10 分钟的值填充到后续每一分钟。数据清洗有个非常容易踩的坑传感器偶发性的异常值。比如某个温度传感器在某个瞬间跳变到 200 度但实际设备温度只有 50 度。这种数据如果不处理模型会被带偏。我用的清洗策略是3σ原则也就是超过均值加减三倍标准差的数据直接剔除再结合前后时刻的值做线性插值补全。时间戳对齐也有讲究。MyEMS 里多台设备的数据可能来自不同的采集网关网关之间的时钟可能存在偏差。我增加了时间戳校准逻辑根据每台设备的报告延迟情况做动态补偿避免模型输入中出现时间错位。2.2 核心特征工程与滑动窗口设计数据清洗完之后接下来是特征构造。CNN-LSTM 虽然能自动提取特征但合理的特征输入能让模型学得更好、学得更快。最终我确定了以下特征集电流三相的均值、标准差、峰峰值电压的有效值和频率波动设备表面温度、轴承温度振动加速度的均方根值功率因数设备运行状态标志启停状态、负载率特征不是越多越好。一开始我尝试加入了上百个特征结果模型训练时间大幅增加准确率却没有明显提升反而引入了不少噪声。后来做了特征重要性分析把对故障预测贡献不大的特征逐步剔除最终保留了一组比较精简的特征集。滑动窗口的设计是整个数据工程中最关键的环节之一。窗口太短模型看不到足够的上下文信息窗口太长又会引入大量无关的历史数据干扰模型的判断。我通过实验对比了 30 分钟、60 分钟、120 分钟三个窗口长度最终选择了 60 分钟。同时预测提前量设置为 60 分钟也就是模型基于过去一个小时的数据预测未来一个小时内设备是否会发生故障。这个设计给运维人员留出了响应窗口。窗口滑动的步长设置为 5 分钟相当于每 5 分钟产生一个新的预测结果。这样做的好处是系统每隔一小段时间就能刷新一次预警状态既不会因为过于频繁的计算浪费资源也不会因为间隔太长而错过故障萌发期的变化。2.3 故障样本不足与类别不均衡处理预测性维护项目最常见的一个问题就是故障数据太少了。大多数时候设备都在正常运行真正发生故障的时段在数据总量中的占比可能连 5% 都不到。如果直接用原始数据训练模型会倾向于把所有的样本都预测为正常因为这样也能获得很高的准确率但没有任何实际意义。我有两个解决方案。第一个是采用滑动窗口的方式切分故障样本。故障发生前的 60 分钟内每个窗口都标记为即将发生故障。这样把一个故障事件扩展成了多个训练样本相当于变相扩充了故障样本数量。第二个方案是过采样和欠采样的组合。对故障样本做轻微的时间偏移增强再随机丢弃一部分正常的样本让训练集中正负样本的比例控制在 1:5 左右。测试集保持真实的数据分布不做任何平衡处理这样评估出来的准确率才有说服力。还有一个细节故障样本和正常样本的时间切分必须严格隔离。如果训练集中某个故障时段的数据和验证集中的数据存在时间重叠会造成数据泄漏导致模型评估结果虚高。我当时专门写了一个时间序列的分割函数确保验证集中的数据时间全部晚于训练集中的数据时间。3. CNN-LSTM 模型构建与训练实战到了模型构建环节很多文章喜欢堆砌模型结构但对实际项目来说模型的结构并不需要太复杂。关键是每个模块的设计要有明确的目的并且在训练过程中通过实验验证每个设计选择的有效性。3.1 模型结构设计细节最终的模型结构是这样的用 PyTorch 实现第一层是一维卷积层。输入形状是 (batch_size, 60, 13)对应 60 个时间步13 个特征维度。卷积核大小设为 3卷积核数量设为 64padding 保持输出长度不变。一维卷积像是一个特征扫描器在时间维度上滑过捕捉短时间内的局部模式。第二层还是卷积层卷积核大小依然是 3但卷积核数量增加到 128进一步提取更高层次的特征。随后接一个最大池化层池化窗口大小为 2降低序列长度减少后续 LSTM 层的计算量。第三层是 LSTM 层隐藏单元数设为 64返回每个时间步的隐藏状态序列。为什么只单层 LSTM 而不是堆叠多层因为我们的数据量有限多层 LSTM 很容易过拟合单层加合理的 dropout 反而泛化能力更好。LSTM 在这里的作用是建模全局的时间依赖关系——哪些局部特征在时间上相继出现对应了怎样的故障演化过程。最后一层是输出层LSTM 最后一步的隐藏状态经过一个全连接层映射到单个数值再经过 Sigmoid 激活函数输出为 0 到 1 之间的故障概率。3.2 训练配置与调参过程损失函数选择的是二元交叉熵损失。优化器用了 Adam初始学习率设为 0.001。训练过程加入了一些我认为非常关键的技巧一是引入了学习率衰减机制。训练过程中如果损失值连续 5 个 epoch 没有下降学习率就乘以 0.5。如果固定学习率不变模型很容易在损失曲面上震荡最终收敛效果不够理想。采用衰减策略之后模型能更快地落入更优的局部极小值区域。二是加入了早停机制。验证集上的损失连续 10 个 epoch 没有改善时就提前终止训练并恢复效果最好的那个 epoch 的模型参数。设置早停主要是为了防止过拟合尤其是我们这种数据量不算大的项目训练时间过长几乎必然导致过拟合。三是批量大小选择。我测试了 32、64、128 几个选项最终选了 64。批量大小过小会导致梯度更新方向震荡影响训练稳定性过大则容易让模型陷入尖锐的极值点泛化能力反而变差。一个值得注意的细节是训练集和验证集的划分方式。前面提到了按时间划分这里再补充一点我按时间段把数据分成了三段最前面的 60% 用于训练中间的 20% 用于验证最后的 20% 用于测试。这样做最大化地模拟了模型部署后的真实场景——用历史数据训练预测未来的数据。3.3 评估方式为什么准确率可以达到 92%关于评估方式我必须多啰嗦几句。分类模型常用的评估指标包括准确率、精确率、召回率、F1 值等但在预测性维护这个场景里不同指标的意义差异非常大。我们说的 92% 准确率具体含义是在测试集上按时间分割后的未见数据模型对所有预测样本中正确预测的比例达到 92%。但只报告准确率是不负责任的我还重点关注了另外几个指标精确率Precision预测为故障且实际确实发生故障的样本占所有预测为故障样本的比例。我们的精确率大约是 89%。召回率Recall实际发生的故障中被模型成功提前预测出来的比例。这个指标对预测性维护来说比精确率更重要——漏掉一次故障预警带来的损失远大于一次误报。我们的召回率大约 95.5%。F1 值精确率和召回率的调和平均大概是 92.1%。为什么要特别强调召回率因为在工业场景下漏报的代价远大于误报。一次漏报意味着设备意外停机可能需要几个小时才能恢复生产而一次误报最多让维护人员多跑一趟检查后确认设备正常即可。所以我在调参时宁愿接受一定的误报比例也要尽量提高召回率。对比来看纯 LSTM 模型的准确率大约是 85%XGBoost 大约是 82%CNN-LSTM 组合模型的 92% 优势明显。差距主要来自 CNN 层对局部特征的提取能力这使得模型能更早地捕捉到故障萌发期的细微信号变化。4. MyEMS 集成与实时推理链路模型训练好只是第一步真正让模型产生价值的是把它部署到实际生产环境中和 MyEMS 平台打通形成实时预警能力。这个环节有不少坑。4.1 模型导出与部署方案训练好的 PyTorch 模型我采用了 ONNX Runtime 的方式部署。先把 PyTorch 模型导出为 ONNX 格式然后在生产服务器上用 ONNX Runtime 加载模型进行推理。每个人的实际部署环境不同选择的方案可能也不同。我这里选 ONNX Runtime主要是看中它的轻量级和低依赖不需要安装完整的 PyTorch 环境推理速度也比 PyTorch 原生的 eager 模式快不少。有人可能会问为什么不用 TensorFlow Serving 或者 Triton 之类的专业推理服务。我当时的考量是项目规模和团队维护能力有限不需要上一个重量级的推理框架。ONNX Runtime 轻量、部署简单单台机器上跑几个并发推理完全没有压力维护成本也低得多。4.2 实时预警逻辑与规则兜底模型部署完成后需要和 MyEMS 的数据流打通。具体流程如下MyEMS 定时采集设备运行数据写入 MySQL 数据库。一个 Python 守护进程每隔 5 分钟从数据库读取最近 60 分钟的设备数据。数据经过和训练时完全相同的预处理逻辑清洗、特征构造、窗口化输入到 ONNX Runtime 推理服务。推理输出故障概率如果概率超过设定的阈值我们设置为 0.7则触发预警。这里有一个非常关键的细节推理前的数据预处理必须和训练时的预处理保持一致。很多项目在模型部署后效果急剧下降原因就是训练和部署时的数据处理流程不一致。我在代码里将清洗和特征变换的逻辑封装成了一个独立的模块训练和推理共用同一套代码从根源上避免了这个坑。预警不是只发一次就完了。为了避免瞬时抖动导致的误报我们设计了连续确认机制连续三次即持续 15 分钟故障概率都超过阈值才正式触发预警。这个机制让误报率下降了接近一半。同时MyEMS 自带的规则告警依然保留。电流超限、温度超限等简单规则由 MyEMS 原有的告警机制负责复杂的趋势性故障预判由我们的 CNN-LSTM 模型负责。这样的双保险机制两者覆盖的范围和场景各有侧重形成互补现场使用起来心里更踏实。4.3 预警效果验证与持续迭代模型上线后我前四周每天都在复盘预警记录。每天做的事有导出前一天模型产生的所有预警记录包括触发时间和对应的故障概率然后去现场确认设备状态把实际结果标记为真故障或误报。第一个月的统计结果是预警 47 次其中真故障 43 次误报 4 次整体准确率 91.5%和测试集上的表现基本一致。后续每个月我还会做一次模型的增量更新。用过去三个月的数据重新训练一次模型替换线上推理服务。这样可以保证模型不至于随着设备老化、工况变化而逐渐失效。模型迭代有一点要特别注意模型版本管理。我每次更新模型都会记录好训练数据的时间范围、训练参数、测试集上的评估指标还要在切换模型前先做一段时间的离线对比评估。新模型在历史数据上的预测效果不低于旧模型才会考虑上线替换。5. 常见问题与排查技巧实录项目落地过程中遇到的问题不少有些问题在标准文档和训练教程里根本不会提到。我把典型的几类整理在这里希望能帮大家少走弯路。5.1 数据缺失导致推理失败或结果异常这个问题在项目上线初期最为突出。某个传感器网络不稳定或者 MyEMS 采集进程重启就会导致一段时间没有数据。如果推理前取到的窗口数据有大量缺失补全后的数据形态会发生明显偏移模型的预测结果也会跟着异常。我的处理方式是在推理模块中增加数据完整性校验如果最近的 60 分钟窗口内缺失值占比超过 20%本次推理直接跳过标记为数据不足不输出预警。宁可少做一次预测也不要用残缺数据产生误导性的输出。等数据恢复完整后系统会自动回归正常推理。5.2 模型上线后准确率低于训练时的表现这是很多人都会遇到的问题但原因往往不是模型本身。我之前遇到过一轮准确率明显下降的情况排查后发现生产环境中实时采集的振动数据格式和训练时的处理方式不一致。训练时的数据经过平滑滤波处理但生产环境拿到的原始数据分辨率更高包含了更多噪声导致模型输入分布发生了偏移。排查问题的逻辑是先检查输入数据的分布是否和训练数据一致再看预处理逻辑是否一致最后才怀疑模型是否需要重新训练。很多情况下模型本身没有问题而是输入端发生了变化。5.3 预警过密运维人员产生告警疲劳项目上线两周后现场反馈预警太多看不过来了。我复盘后发现有些预警确实是有价值的但也有一些是设备处于正常波动状态时触发的属于误报。除了前面提到的连续确认机制我又增加了两个优化一是设置了触发间隔。同一台设备触发预警后24 小时内不会重复触发相同类型的预警防止同一个故障萌芽阶段反复刷屏。二是增加了严重程度分级。故障概率 0.7 到 0.85 之间属于黄色预警只推送消息0.85 以上属于红色预警直接电话通知到值班人员。分级机制让现场人员能分清轻重缓急把精力放在更紧急的事务上。5.4 设备正常运行和故障运行工况差异大还有一个比较棘手的问题设备在不同负载率下正常运行的信号特征变化非常大。比如低负载运行时的振动水平和高负载运行时的振动水平可能相差数倍。如果模型不分工况地用一个标准来判断很容易在低负载阶段产生误报。我的解决方案是在特征中加入负载率信息并且在模型训练时把不同工况下的数据都纳入进来。实际使用下来效果有改善但这个问题现在并没有完全杜绝。后续如果有精力我可能会尝试按照工况分组建模给不同负载区间各训练一个专用模型这应该是更彻底的方向。6. 写在最后这个方案还能怎么走这个项目做到现在92% 的预警准确率算是一个阶段性的成果。但工业预测性维护是一个需要长期迭代和持续投入的方向模型的准确率不会永远保持高位。随着设备老化、工况变化模型需要定期更新和维护。我个人的体会是预测性维护最难的部分从来不是模型的搭建而是把它嵌入到实际的业务流程中让一线人员愿意用、用得起来。准确率再高如果预警结果不被信任、不被处理一切都等于零。所以如果你也打算在自己的项目里做类似的尝试我会建议你把精力多放在三个方向上第一把数据基础打扎实数据质量决定了模型的天花板第二重视预警的交互逻辑设计不仅仅是技术方案也要考虑使用者的感受第三建立一个可持续的模型迭代机制让系统能够随着数据积累越用越准。CNN-LSTM 模型的 92% 准确率不是终点它只是在验证了这条路走得通。真正有价值的是背后的这一整套从数据采集、特征构建、模型训练到系统集成的完整工程链路以及这条链路里每一个环节的经验沉淀。希望对正在做类似探索的朋友有所启发。