设备维修保养系统预测性维护不用深度学习?设备健康度评分的务实实现方案
引言:客户要"预测故障",我们要的其实是"少坏"
每次给客户演示运维系统,都会被问同一个问题:"你们能预测设备什么时候坏吗?"
早期我们的回答很诚实:"不能,但我们可以告诉你这台设备正在变差。"后来发现,这恰恰是绝大多数客户真正需要的东西——他们不要求未卜先知,他们要的是:在设备彻底罢工前,有足够的时间窗口去安排检修,而不是半夜接到停机电话。
所以本文不聊深度学习,聊一套在十几个现场验证过的设备健康度评分方案:怎么选指标、怎么消除"夏天温度天然高"的误报、怎么用"劣化速率"抓住真问题。方法朴素,但胜在客户看得懂、现场跑得稳。
一、评分模型:四个维度,少即是多
第一版我们恨不得把所有采集点都塞进评分模型,结果客户看着一个 73 分反问:"73 分是什么意思?我该干什么?"评分如果解释不了,就等于没有评分。最终收敛为四个维度,每个维度客户都能对应到具体动作:
| 维度 | 权重 | 数据来源 | 分数低说明什么 |
|---|---|---|---|
| 状态指标劣化 | 40% | 传感器采集(温度/振动/电流) | 某项物理量正在偏离正常区间 |
| 保养执行情况 | 25% | 工单系统 | 该做的保养欠账了 |
| 故障历史 | 20% | 工单系统的故障记录 | 近期反复出毛病 |
| 运行时长 | 15% | 采集 + 台账 | 接近大修周期 |
总分 0~100,90 以上健康,70~90 关注,60~70 预警,60 以下建议停机检查。阈值不重要,可解释才重要——每个维度的扣分项都能下钻到具体数据,这才是设备主管要的。
核心计算结构:
public class HealthScore {
public int compute(Device device, MetricWindow window) {
int statusScore = statusEvaluator.eval(device, window); // 0~100,含动态基线
int maintainScore = maintenanceEvaluator.eval(device); // 欠保养扣分
int faultScore = faultHistoryEvaluator.eval(device); // 近90天故障加权
int runtimeScore = runtimeEvaluator.eval(device); // 大修周期进度
return (int) (statusScore * 0.40 + maintainScore * 0.25
+ faultScore * 0.20 + runtimeScore * 0.15);
}
}
二、动态基线:治好"夏天温度高"的误报
状态指标评分最大的坑是静态阈值。给空压机排气温度设一个 85℃ 告警线,冬天永远不报警,夏天天天报警——客户两周后就会关掉通知。
我们的做法是为每个测点建立动态基线:按"小时 + 星期"分桶统计历史数据,正常区间跟着季节和作息走:
import numpy as np
from collections import defaultdict
def build_baseline(history: list, key=lambda p: (p["ts"].hour, p["ts"].weekday())):
"""history: 近30天该测点的 {'ts': datetime, 'value': float} 列表"""
buckets = defaultdict(list)
for p in history:
buckets[key(p)].append(p["value"])
baseline = {}
for k, values in buckets.items():
arr = np.array(values)
baseline[k] = {
"mean": float(np.mean(arr)),
"std": float(np.std(arr)),
}
return baseline
def score_point(value: float, baseline: dict, ts) -> float:
b = baseline.get((ts.hour, ts.weekday()), min(baseline.values(), key=lambda x: x["mean"]))
# 偏离基线 3σ 记 0 分,2σ 记 60 分,σ 内记满分
deviation = abs(value - b["mean"]) / max(b["std"], 1e-6)
if deviation >= 3: return 0
if deviation <= 2: return 100
return max(0, int(100 - (deviation - 2) * 40))
两个工程细节:
- 基线必须排除已确认的异常时段。某次设备故障持续三天,那三天的数据如果混进基线,"坏的状态"就成了新的正常。我们的做法是:告警确认后的时段数据打上污染标记,基线计算时剔除。
- 冷启动降级。新接入的设备没有 30 天历史,先用同型号设备的基线模板顶上,同时界面上标注"学习期,评分仅供参考"。假装精确比承认不准确更伤信任。
三、劣化速率:比绝对值更早的信号
绝对值评分有个盲区:一台设备温度从 70℃ 缓慢爬到 82℃,始终没破线,评分一直挺高,然后在某个凌晨直接故障。
劣化速率是比绝对值更早的信号。我们对关键测点同时计算 7 日滑动斜率:
-- 7日斜率:线性回归简化版(首尾差值 / 天数),小时级数据聚合后计算
SELECT device_id, metric_code,
(MAX(CASE WHEN rk = 1 THEN avg_value END)
- MIN(CASE WHEN rk = 1 THEN avg_value END))
/ (MAX(day_no) - MIN(day_no)) AS slope_per_day
FROM (
SELECT device_id, metric_code, day_no, avg_value,
ROW_NUMBER() OVER (PARTITION BY device_id, metric_code
ORDER BY day_no) AS rk
FROM metric_daily_agg
WHERE day_no >= CURDATE() - INTERVAL 7 DAY
) t
GROUP BY device_id, metric_code
HAVING COUNT(*) >= 5; -- 数据点太少不评估
斜率超过该测点设定阈值时,即使绝对值正常也触发"劣化趋势"预警,并自动降低健康分。这个机制上线后抓到的第一类典型问题就是空压机缓慢漏气——压力每天掉一点点,绝对值告警永远不响。
四、上线之后:误报治理是一场持久战
诚实地说,这套系统上线第一个月的误报率是 41%,主要来自三个原因和对应的治理:
- 点表/单位配错(占误报一半)。某测点配置里 scale 写错,数值放大十倍,天天高分预警。治理:接入清单强制"现场人工核对三个真实值再启用评分"。
- 工艺性波动。客户周三下午固定全负荷生产,温度天然冲高。治理:动态基线基本吸收了这类波动,剩余的用"时段豁免"配置兜底。
- 传感器本身坏了。振动传感器松动后读数飘忽,系统报"设备劣化",实际是传感器要修。治理:加了一条经验规则——某个测点读数"跳变频率异常高"时,优先提示检查传感器,而不是设备。
第三个月误报率降到 9% 左右,设备主管从"把通知关掉"变成了"每周一早上先看健康分榜"。这个转变比任何算法指标都珍贵。

五、踩坑记录
坑一:评分算在云端,网络断了评分就"消失"。客户问"昨天你们系统怎么没推送健康日报",其实是我们统计任务依赖的采集通道断了半天。后来评分任务对数据缺失做显式标注("数据完整率 62%,评分置信度低"),而不是静默给出一个看似正常的结果。
坑二:全部测点实时评分,计算集群撑不住。几千台设备 × 几十个测点每分钟算一遍纯属浪费。改为分级:关键测点 5 分钟算,一般测点小时级批量算,评分本身只要小时级新鲜度。
坑三:分数突变没有归因。健康分从 88 掉到 65,客户第一反应是"系统坏了"。后来每次分数骤降 15 分以上,自动附上扣分归因("保养逾期 2 项、排气温度偏离基线 2.8σ"),客诉立减。
写在最后
预测性维护这个词很大,但落地到中小制造企业,一个可解释、误报可控的健康度评分,价值远大于一个黑盒模型。我们这套方案的全部前提只有一个:前面的采集链路是通的——这正是上一篇讲的 MQTT/Modbus/OPC UA 三件套的意义。数据质量决定了评分上限,算法只是在数据质量的帽子下面跳舞。
多数设备运维场景不需要深度学习。本文给出一套务实的设备健康度评分方案:指标选取与权重设计、动态基线去除季节波动、劣化速率预警,附完整计算代码与上线后的误报治理数据。
浙公网安备 33010602011771号