算法由以下脚本实现:
backend/scan_pks_fault_evolution.py
脚本为只读扫描器,只查询数据库,不修改数据库。主要输出:
报警阈值配置.csv
润滑油压力小时等级.csv
润滑油压力小时阶段段.csv
润滑油压力演化周期.csv
振动异常段.csv
| 点位 | 含义 | 用途 |
|---|---|---|
YSJ_5 |
润滑油压力 | 分析长期下降和低压风险 |
YSJ_10 |
联轴器端振动 | 分析振动峰值和均值异常 |
YSJ_11 |
链轮端振动 | 分析振动峰值和均值异常 |
YSJ_41 |
运行状态 | 判断设备是否运行 |
运行判断规则:
YSJ_41 > 0 表示设备运行
批次与机组的对应关系:
| 批次 | 机组 |
|---|---|
| 30 | 7号机 |
| 31 | 8号机 |
| 32 | 9号机 |
数据库端按小时聚合 5 秒采样数据,每个小时计算:
每小时理论样本数为:
720 个样本(5 秒一个样本)
运行覆盖率计算方式:
运行覆盖率 = 运行样本数 / 720
只有满足以下条件的小时,才参与长期趋势或振动基线分析:
运行覆盖率 >= 0.80
这样可以排除停机、启动、停机过渡和采集不完整对结果的影响。
识别润滑油压力是否出现真实的长期恶化,而不是把单个采样点或短时掉点误判为长期故障。
核心思想:
周期基线 + 下降百分比 + 持续下降趋势 + 工程报警阈值 + 连续确认
对每台机组的有效运行小时建立油压周期:
周期基线取周期开始阶段前 24 个有效运行小时油压均值的中位数:
周期基线 = 前 24 个有效小时油压均值的中位数
同时计算近期 24 个有效小时基线,用于辅助判断当前油压是否偏离近期水平。
对最近 6 个有效运行小时计算油压线性斜率,并统计连续下降的有效小时数。
认为油压处于下降趋势的条件为:
连续下降有效小时数 >= 3
或最近 6 个有效小时斜率 < -0.0005
相对周期基线变化计算方式:
相对变化 = (当前油压 - 周期基线) / 周期基线
例如结果为 -16.7%,表示当前油压比周期基线下降约 16.7%。
同时满足:
相对周期基线下降 >= 5%
且处于下降趋势
满足任一条件:
相对周期基线下降 >= 10%,且处于下降趋势
或油压 <= 低报警阈值
满足任一条件:
相对周期基线下降 >= 20%,且处于下降趋势
或油压 <= 低低报警阈值
当前实际阈值示例:
低报警阈值:0.34 MPa
低低报警阈值:0.31 MPa
报警阈值从数据库中的 site_point 和对应 AlarmType 配置读取,不固定写死某一个报警配置编号。
一个小时内,只有当达到报警阈值的运行样本占比至少达到 20% 时,才将该小时标记为对应的低报警小时:
报警样本比例 = 报警运行样本数 / 运行样本数
报警样本比例 >= 20%
为减少短时异常误报,油压阶段采用连续有效小时确认:
因此,短时间低压掉点不会直接形成长期严重故障阶段,但原始报警不会丢失。
油压结果分为三层:
阶段合并时,同一机组、同一周期、同一等级且间隔不超过 6 小时的小时会合并。
典型演化结果:
轻微 -> 异常 -> 严重异常
识别两类振动异常:
核心思想:
工程报警阈值 + 历史稳健基线 + 均值偏离 + 峰值偏离 + 时间段合并
对联轴器端和链轮端分别计算历史基线,使用当前小时之前最多 336 个有效运行小时:
336 小时约等于 14 天
至少需要 24 个历史有效运行小时,才开始进行振动异常判断。
基线采用稳健统计方法:
中心 = 中位数
波动尺度 = max(1.4826 × MAD, |中心| × 5%, 极小值)
其中 MAD 是中位绝对偏差,可以降低异常峰值对基线的影响。
振动均值和振动最大值分别建立基线,并计算当前值相对基线的偏离程度。
任一条件满足即可:
高高报警样本比例 >= 1%
或振动峰值 >= 高高报警阈值
或峰值相对基线偏离 >= 8 个稳健尺度
当前高高报警阈值示例:
8.5 mm/s
任一条件满足即可:
高报警样本比例 >= 1%
或振动峰值 >= 高报警阈值
或峰值相对基线偏离 >= 5 个稳健尺度
或振动均值相对基线偏离 >= 4 个稳健尺度
当前高报警阈值示例:
7.1 mm/s
满足任一条件:
峰值相对基线偏离 >= 4 个稳健尺度
或均值相对基线偏离 >= 3 个稳健尺度
联轴器端和链轮端分别判断后:
这样可以识别单侧机械异常,也可以识别两侧同步升高的情况。
相邻触发小时之间间隔不超过 6 小时,会合并为同一个振动异常段。
异常段保留条件:
至少有 1 个严重信号小时
或至少有 2 个触发小时
因此:
振动异常段会进一步标记变化形态:
对活塞、机械部件等故障,重点关注:
链轮端峰值突然增加、在不同运行时段重复出现,但平均振动不一定持续升高
对气阀相关异常,重点关注:
某侧振动整体抬高,随后出现高峰
python backend/scan_pks_fault_evolution.py --help
| 参数 | 含义 | 默认值 |
|---|---|---|
--batch |
批次,可多选 | 30 31 32 |
--start |
开始时间 | 2025-04-01 00:00:00 |
--end |
结束时间 | 2026-05-01 00:00:00 |
--chunk-days |
每个数据库查询块的天数 | 14 |
--output-dir |
输出目录 | cache/pks_scanner/evolution |
批次对应关系:
30 = 7号机
31 = 8号机
32 = 9号机
python backend/scan_pks_fault_evolution.py
python backend/scan_pks_fault_evolution.py \
--batch 30 31 32 \
--start "2025-04-01 00:00:00" \
--end "2026-05-01 00:00:00" \
--chunk-days 14 \
--output-dir cache/pks_scanner/evolution_pct_confirmed
python backend/scan_pks_fault_evolution.py \
--batch 31 \
--start "2025-10-20 00:00:00" \
--end "2025-11-05 00:00:00" \
--chunk-days 7 \
--output-dir cache/pks_scanner/evolution_8_verify
优先看以下字段:
相对周期基线变化;近6有效小时油压斜率;连续下降有效小时数;压力等级;是否形成确认等级;低报警小时数、低低报警小时数。判断重点:
是否在完整运行小时内持续下降,并且连续达到确认时长
优先看以下字段:
振动阶段;阶段综合评分及各项分项得分;最强异常侧;阶段最大振动值;最强侧近期峰值基线和最强侧近期稳健尺度;阶段最大峰值/基线比例;阶段最大连续异常有效小时数。判断重点:
峰值是否真实发生在完整运行小时内,是否重复出现,均值是否同步抬升
振动阶段使用持续时间、平均振动抬升、阶段最大振动值和峰值稳健偏离进行综合评分,总分 0~100 分:
持续时间 40 分 + 平均振动 20 分 + 最大振动值 20 分 + 峰值稳健偏离 20 分
评分分级:
达到以下任一条件时直接判定为严重异常:峰值达到高高报警阈值、存在高高报警小时,或峰值达到 8 个稳健尺度且阶段至少包含 2 个有效运行小时。
其中:
近期峰值基线 = 前 336 个有效运行小时的峰值中位数
稳健尺度 = max(1.4826 × MAD, |近期峰值基线| × 5%, 极小值)
峰值稳健偏离 = (当前峰值 - 近期峰值基线) / 稳健尺度
峰值/基线比例 = 当前峰值 / 近期峰值基线
例如峰值稳健偏离 19.43,表示当前峰值高于近期基线 19.43 个稳健尺度;如果峰值/基线比例为 2.41,则表示当前峰值约为基线的 2.41 倍。两者含义不同。
运行样本数 / 720 一起查看,避免低覆盖率小时造成误判。本方案用于对现有规则结果进行相似性判断和辅助确认,不预测未来,也不替代 backend/scan_pks_fault_evolution.py 的阶段划分和异常规则。
原始采样数据
→ 沿用现有脚本按自然小时聚合
→ 沿用运行覆盖率、开停机和有效小时判断
→ 分别形成油压窗口和振动窗口
→ XGBoost 分类 + K 近邻相似性匹配
→ 与现有规则结果联合展示和辅助确认
润滑油压力和振动分别建立模型,不混合训练。模型输入、标签和实时输入必须使用与现有脚本相同的小时边界及基础特征。
YSJ_41 > 0 用于判断运行状态,运行覆盖率低于 80% 的小时不进入模型窗口。后续实现时,模型数据准备应直接复用 backend/scan_pks_fault_evolution.py 的数据读取和小时聚合逻辑,不要为模型另外编写一套时间处理方式。推荐先形成一张“小时级中间表”,再从中间表生成压力窗口和振动窗口。
sample_time:原始采样时间;machine 或现有设备标识字段;batch 或现有批次字段;YSJ_41:运行状态判断点;YSJ_10:联轴器端振动;YSJ_11:链轮端振动;每个原始采样点先按以下方式归入小时:
hour = sample_time 向下取整到整点
每个“设备 + 批次 + 小时”生成一行小时数据,至少包括:
机组/设备
批次
小时
总采样数
运行样本数
运行覆盖率 = 运行样本数 / 720
油压均值、最小值、最大值
YSJ_10 均值、最大值
YSJ_11 均值、最大值
油压低报警样本数、低低报警样本数
振动高报警样本数、高高报警样本数
其中运行样本的定义必须保持一致:
YSJ_41 > 0
只有以下小时才可进入有效运行小时序列:
运行覆盖率 >= 0.80
且所需的压力或振动特征不为空
压力模型只要求油压特征有效;振动模型只要求 YSJ_10、YSJ_11 至少有可用特征。不能因为某一类特征缺失,就把另一类模型的有效小时强行删除。
在生成窗口前,先为每台设备建立运行状态边界信息。对相邻有效运行小时计算时间间隔:
间隔 > 12 小时:新的运行周期
间隔 <= 12 小时:仍属于同一运行序列
同时标记以下小时:
首次有效运行小时
长停机后的重启首个有效运行小时
停机前最后 1~2 个有效运行小时
这些标记不应丢失,后续既用于生成正常标签,也用于解释模型结果。窗口生成时不得跨越新的运行周期。
每个窗口必须属于同一台设备、同一批次和同一运行周期,并包含连续 6 个有效运行小时。窗口按有效运行小时序列滑动,而不是按数据库行号或简单自然小时滑动。
假设某个运行周期的有效小时序列为:
h1, h2, h3, h4, h5, h6, h7, h8
则生成:
窗口1:h1~h6
窗口2:h2~h7
窗口3:h3~h8
每个窗口保存以下索引字段:
window_id
机组/设备
批次
运行周期编号
窗口开始小时
窗口结束小时
窗口内有效运行小时数 = 6
窗口内自然持续小时数
如果某个窗口中出现以下情况,则不生成该窗口:
窗口结束时间是模型当前可以看到的最后一个小时。实时运行时,只使用截至该窗口结束小时已经产生的数据,不能使用后续小时的数据。
每个 6 小时窗口提取统计、趋势和基线偏离特征,不直接把阶段最终结果作为输入,避免使用未来信息。
压力模型主要特征:
振动模型主要特征:
YSJ_10、YSJ_11 的 6 小时均值、最大值和变化幅度;两个结果 CSV 分别作为两个模型的阶段标签来源:
润滑油压力小时阶段段.csv → 压力异常窗口标签;振动异常段.csv → 振动异常窗口标签。第一阶段只划分二分类:
正常窗口 / 压力异常窗口
正常窗口 / 振动异常窗口
暂不把轻微、异常、严重异常分别训练成多分类,原因是当前独立故障过程和严重异常样本较少。一个 6 小时窗口如果落在对应异常阶段内,可标记为异常窗口;跨越异常边界或处于异常前后 12 小时隔离区的窗口暂不作为正常标签。
同一完整故障过程切出的多个窗口属于同一组,训练集和测试集不得拆散到两边,避免因窗口高度重叠造成结果虚高。
正常样本应从已确认稳定运行的连续数据中均匀抽取,按压缩机、月份或运行周期进行分层,避免正常样本集中在某一台设备或某一段时间。采集前必须确认:
正常样本数量不需要无限增加,应尽量与异常窗口保持合理比例,并保证不同设备和时间段都有代表性。
每个方向使用一个 XGBoost 二分类模型,并同时保留 K 近邻相似性匹配:
示例输出:
压力规则:正常
压力模型异常概率:0.68
最相似历史压力异常窗口:0.79
辅助判断:存在压力异常相似性,继续观察
模型不能单独推翻现有规则的严重异常结果。实际判断建议分为:
当前样本量较少,模型定位为历史故障相似性匹配和规则辅助确认,不作为独立故障诊断器。压力和振动应分别评估,不能把滑动窗口数量当成独立故障数量。后续只有在积累更多独立故障过程,并结合维修记录或人工确认校验标签后,才考虑进一步训练多等级模型。
模型不是另起一套故障检测程序,而是接在 backend/scan_pks_fault_evolution.py 之后,使用扫描器已经生成的小时数据、运行状态和规则结果。联合判断的原则是:
现有扫描器负责发现和划分异常阶段
模型负责判断当前窗口是否像历史异常
联合层负责给出辅助确认结果
每当新的完整小时数据到达后,按以下顺序执行:
1. 读取最新原始采样数据
2. 按现有规则聚合为自然小时数据
3. 判断运行状态和运行覆盖率
4. 更新该设备的有效运行小时序列
5. 更新压力周期和压力基线
6. 更新振动近期稳健基线
7. 执行现有压力、振动规则
8. 判断是否已经形成或更新异常阶段
9. 如果已有最近6个有效运行小时,则生成模型窗口
10. 提取与训练时完全相同的窗口特征
11. 分别调用压力模型和振动模型
12. 查询最相似的历史窗口
13. 将规则结果、模型概率和相似度合并输出
在第 9 步之前不能调用模型。少于 6 个有效运行小时,窗口不完整,只能输出现有规则结果,不能人为补齐窗口。
压力方向使用独立的压力模型,处理顺序如下:
最新有效压力小时
↓
加入当前压力周期
↓
更新周期基线和最近趋势
↓
执行现有压力小时规则
↓
生成最近6个有效运行小时的压力窗口
↓
计算窗口特征
↓
XGBoost压力模型 + K近邻压力相似度
↓
与压力规则结果合并
压力规则仍然负责:
润滑油压力小时等级.csv 和 润滑油压力小时阶段段.csv。压力模型只负责回答:
最近6个有效运行小时的压力变化,是否像历史压力异常窗口?
建议压力联合输出至少包含:
设备
窗口开始小时
窗口结束小时
现有压力小时等级
现有压力阶段编号(如果已经形成)
压力模型异常概率
最相似历史压力窗口
压力相似度
压力联合判断
压力联合判断建议使用以下逻辑:
| 现有规则 | 模型结果 | 联合输出 |
|---|---|---|
| 正常 | 概率和相似度都低 | 正常 |
| 正常 | 概率或相似度较高 | 压力疑似异常,继续观察,不直接升级阶段 |
| 轻微 | 模型支持较高 | 压力异常倾向,辅助确认 |
| 异常/严重异常 | 模型支持较高 | 模型辅助确认压力异常 |
| 异常/严重异常 | 模型支持较低 | 保留规则结果,标记模型意见不一致,人工复核 |
模型不能因为概率较低就取消现有规则已经确认的压力异常,也不能因为概率较高就绕过现有规则直接生成严重异常阶段。
振动方向使用独立的振动模型,处理顺序如下:
最新有效振动小时
↓
判断是否为重启后的首个有效运行小时
↓
更新前336个有效运行小时的振动基线
↓
执行YSJ_10、YSJ_11小时级振动规则
↓
按6小时间隔合并振动信号
↓
生成最近6个有效运行小时的振动窗口
↓
计算YSJ_10、YSJ_11窗口特征
↓
XGBoost振动模型 + K近邻振动相似度
↓
与振动规则结果合并
振动规则仍然负责:
YSJ_10 和 YSJ_11 是否触发振动信号;振动异常段.csv。振动模型只负责回答:
最近6个有效运行小时的振动变化,是否像历史振动异常窗口?
重启后的首个有效运行小时不生成振动模型窗口,也不作为振动正常样本。必须等到后续累计满 6 个合格有效运行小时后,才可以进行模型判断。
建议振动联合输出至少包含:
设备
窗口开始小时
窗口结束小时
现有振动规则等级
异常侧:YSJ_10 / YSJ_11 / 两侧
现有振动阶段编号(如果已经形成)
振动模型异常概率
最相似历史振动窗口
振动相似度
振动联合判断
联合系统中,两个部分的职责必须固定,不能在实现过程中互相覆盖:
| 功能 | 现有扫描器 | 模型辅助层 |
|---|---|---|
| 小时聚合 | 负责 | 不重复实现 |
| 运行状态判断 | 负责 | 使用结果 |
| 有效小时判断 | 负责 | 使用结果 |
| 开停机边界 | 负责 | 使用结果并过滤窗口 |
| 压力/振动基线 | 负责更新 | 使用同口径特征 |
| 单小时异常识别 | 负责 | 不直接替代 |
| 异常阶段合并 | 负责 | 不直接替代 |
| 历史相似性判断 | 不负责 | 负责 |
| 异常概率输出 | 不负责 | 负责 |
| 最终规则结果 | 负责 | 提供辅助意见 |
因此,模型输出不应直接改写两个现有结果 CSV。第一阶段建议单独输出模型辅助结果,例如:
压力模型辅助确认.csv
振动模型辅助确认.csv
这样可以在不影响现有规则结果的情况下,对比模型与规则的一致性。
为了避免只输出一个难以解释的布尔值,联合层建议使用以下状态:
规则正常
规则轻微异常
规则异常
规则严重异常
模型疑似异常
模型辅助确认
规则与模型不一致
数据不足
具体判断优先级如下:
概率和相似度的具体阈值不能直接凭经验固定。应在独立验证数据上确定,例如分别评估不同阈值下的误报数量、异常召回情况和规则一致率。阈值确定前,模型结果只能作为参考,不应自动升级报警。
模型窗口和规则阶段不是一一对应关系:
因此,模型结果应通过 设备 + 批次 + 窗口结束小时 与规则小时结果关联,再根据窗口时间范围判断它是否落在规则阶段内,而不能简单按行号或阶段编号直接关联。
推荐关联方式:
规则小时记录:设备、批次、小时
模型窗口记录:设备、批次、窗口开始小时、窗口结束小时
阶段记录:设备、批次、开始小时、结束小时
实时判断时,以模型窗口的 窗口结束小时 作为当前判断时刻:
模型窗口结束小时 = 当前最新有效小时
如果模型窗口结束小时已经落入规则异常阶段,模型结果用于确认;如果尚未落入规则阶段但模型支持较高,只能标记为疑似异常,不能提前修改规则阶段起点。
pks_long_sample 原始采样数据
↓
scan_pks_fault_evolution.py:按自然小时聚合
↓
小时级中间表
├─ 运行样本数、运行覆盖率
├─ 油压小时特征
├─ YSJ_10 小时特征
├─ YSJ_11 小时特征
└─ 报警比例和状态边界
↓
现有规则分支
├─ 压力小时等级
├─ 压力异常阶段
└─ 振动异常阶段
↓
模型窗口分支
├─ 最近6个有效运行小时压力窗口
│ ├─ 压力窗口特征
│ ├─ XGBoost压力异常概率
│ └─ K近邻压力相似度
└─ 最近6个有效运行小时振动窗口
├─ 振动窗口特征
├─ XGBoost振动异常概率
└─ K近邻振动相似度
↓
联合判断层
├─ 按设备、批次、窗口结束小时关联规则结果
├─ 保留规则阶段和等级
├─ 增加模型概率和历史相似案例
└─ 输出模型辅助确认结果
第一阶段的实现顺序建议为:
1. 先输出小时级中间表
2. 验证模型窗口与现有规则的时间完全对齐
3. 生成压力和振动6小时窗口
4. 生成正常/异常标签
5. 先离线训练和评估XGBoost、K近邻
6. 输出独立模型辅助结果,不修改现有规则CSV
7. 对比规则与模型结果
8. 确认阈值后,再考虑接入实时联合判断