设备维修保养系统预测性维护不用深度学习?设备健康度评分的务实实现方案

引言:客户要"预测故障",我们要的其实是"少坏"

每次给客户演示运维系统,都会被问同一个问题:"你们能预测设备什么时候坏吗?"

早期我们的回答很诚实:"不能,但我们可以告诉你这台设备正在变差。"后来发现,这恰恰是绝大多数客户真正需要的东西——他们不要求未卜先知,他们要的是:在设备彻底罢工前,有足够的时间窗口去安排检修,而不是半夜接到停机电话。

所以本文不聊深度学习,聊一套在十几个现场验证过的设备健康度评分方案:怎么选指标、怎么消除"夏天温度天然高"的误报、怎么用"劣化速率"抓住真问题。方法朴素,但胜在客户看得懂、现场跑得稳。

一、评分模型:四个维度,少即是多

第一版我们恨不得把所有采集点都塞进评分模型,结果客户看着一个 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))

两个工程细节:

  1. 基线必须排除已确认的异常时段。某次设备故障持续三天,那三天的数据如果混进基线,"坏的状态"就成了新的正常。我们的做法是:告警确认后的时段数据打上污染标记,基线计算时剔除。
  2. 冷启动降级。新接入的设备没有 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%,主要来自三个原因和对应的治理:

  1. 点表/单位配错(占误报一半)。某测点配置里 scale 写错,数值放大十倍,天天高分预警。治理:接入清单强制"现场人工核对三个真实值再启用评分"。
  2. 工艺性波动。客户周三下午固定全负荷生产,温度天然冲高。治理:动态基线基本吸收了这类波动,剩余的用"时段豁免"配置兜底。
  3. 传感器本身坏了。振动传感器松动后读数飘忽,系统报"设备劣化",实际是传感器要修。治理:加了一条经验规则——某个测点读数"跳变频率异常高"时,优先提示检查传感器,而不是设备。

第三个月误报率降到 9% 左右,设备主管从"把通知关掉"变成了"每周一早上先看健康分榜"。这个转变比任何算法指标都珍贵。

设备售后运维管理系统介绍

五、踩坑记录

坑一:评分算在云端,网络断了评分就"消失"。客户问"昨天你们系统怎么没推送健康日报",其实是我们统计任务依赖的采集通道断了半天。后来评分任务对数据缺失做显式标注("数据完整率 62%,评分置信度低"),而不是静默给出一个看似正常的结果。

坑二:全部测点实时评分,计算集群撑不住。几千台设备 × 几十个测点每分钟算一遍纯属浪费。改为分级:关键测点 5 分钟算,一般测点小时级批量算,评分本身只要小时级新鲜度。

坑三:分数突变没有归因。健康分从 88 掉到 65,客户第一反应是"系统坏了"。后来每次分数骤降 15 分以上,自动附上扣分归因("保养逾期 2 项、排气温度偏离基线 2.8σ"),客诉立减。

写在最后

预测性维护这个词很大,但落地到中小制造企业,一个可解释、误报可控的健康度评分,价值远大于一个黑盒模型。我们这套方案的全部前提只有一个:前面的采集链路是通的——这正是上一篇讲的 MQTT/Modbus/OPC UA 三件套的意义。数据质量决定了评分上限,算法只是在数据质量的帽子下面跳舞。

posted on 2026-08-31 18:19  程序员李铁牛  阅读(27)  评论(0)    收藏  举报