惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

罗磊的独立博客
爱范儿
爱范儿
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
博客园_首页
博客园 - 叶小钗
酷 壳 – CoolShell
酷 壳 – CoolShell
Apple Machine Learning Research
Apple Machine Learning Research
云风的 BLOG
云风的 BLOG
量子位
博客园 - 三生石上(FineUI控件)
Stack Overflow Blog
Stack Overflow Blog
小众软件
小众软件
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
V
V2EX
人人都是产品经理
人人都是产品经理
V
Visual Studio Blog
Jina AI
Jina AI
L
LangChain Blog
M
MIT News - Artificial intelligence
MongoDB | Blog
MongoDB | Blog
Last Week in AI
Last Week in AI
Martin Fowler
Martin Fowler
WordPress大学
WordPress大学

博客园 - 程序员李铁牛

赛事报名系统开发:角色与权限体系设计 赛事系统报名接龙高并发技术细节处理浅析 档案数字化研发手记:PDF合并内存溢出踩坑 纸质档案数字化管理系统研发手记:法院诉讼档案单套制落地案例复盘——从纸质卷宗到电子卷宗 档案数字化管理系统开发手记:人事档案专项审核与数字化的系统支撑——"凡提必审"下的技术要点 档案数字化研发手记:我们的技术栈选择——档案系统前后端选型理由(含一次"炫技"的教训) 社群团购系统开发分享——工程化(下):资金支付测试策略——资金模块 100% 覆盖,其他 60% 就够 社群团购系统类快团团源码开发——工程化(上):一套让 5 人小团队不出事故的开发规范 社群团购类快团团系统开发——RBAC 权限设计源码分析:当一个微信号有 4 种身份时怎么办 社群团购系统类快团团模式开发——微信小程序登录:code2Session 之后还有 5 件事要做 数字档案管理系统化研发手记:医院病历档案数字化——合规、病案首页 OCR 与调阅提速 数字档案系统研发手记:批量扫描任务调度——TWAIN/SANE 采集驱动的封装实践 档案数字化系统研发源码手记:置信度过滤——把 97% 识别率变成真正可交付的成果 档案数字化开发实例手记:盖章遮挡文字识别恢复 景区运营预约系统开发:景区会员体系怎么搭?3级会员模型+积分玩法 景区门票预约系统全渠道平台库存数据同步技术处理方式 系统宕机了怎么办?景区票务系统应急预案模板 景区门票预约系统开发:接入AI预测客流设计思路分析 景区预约系统开发总结:门票分时预约设计原理和落地方法 设备运维管理系统开发实战:用规则引擎实现可配置的设备告警策略自研轻量引擎 vs Drools 落地对比 档案数字化管理系统研发手记:档案权限模型——全宗-门类-案卷-文件四级控制的设计与实践 档案管理信息化系统研发手记:数字水印方案对比——可见水印 vs 盲水印(档案借阅防泄露) 景区票务系统开发实例分析:上云还是本地部署?6个维度判断 档案数字化系统源码研发手记:老旧档案去污点——中值滤波与 inpainting 效果对比 一物一码防伪溯源系统开发全栈源码串联一次扫码的完整链路追踪代码走读 景区门票预约系统票务系统的6个核心模块 景区上线门票预约系统的5个常见翻车点 景区门票预约系统之人脸识别 vs 身份证核验 vs 扫码入园,哪种最适合你? 景区门票预约系统开发深度解析之定价策略功能设计 景区门票预约系统开发深度解析
设备维修保养系统预测性维护不用深度学习?设备健康度评分的...
程序员李铁牛 · 2026-08-31 · via 博客园 - 程序员李铁牛

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

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

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

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

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

第一版我们恨不得把所有采集点都塞进评分模型,结果客户看着一个 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 三件套的意义。数据质量决定了评分上限,算法只是在数据质量的帽子下面跳舞。