4. 压窜起跳点的滑动窗口检测

滑动窗口统计量为什么能抓住“起跳点”

压窜起跳点不是压力绝对值的突变,而是局部统计特性的改变:起跳前窗口内压力增量近似零均值噪声,起跳后窗口内出现持续同号增量。因此用两个相邻滑动窗口做对比统计,比直接对原始压力设阈值更稳健。本节采用的核心统计量是双窗口均值差 Z 值:

设压力序列为 p[i],前窗长度 L、后窗长度 L,步长 1。对每个候选位置 k:

m1 = mean(p[k-L : k])          # 前窗均值
m2 = mean(p[k : k+L])          # 后窗均值
s  = std( diff(p[k-L : k+L]) ) # 局部一阶差分标准差(噪声尺度)
Z[k] = (m2 - m1) / (s / sqrt(L) + eps)

Z 值本质是“后窗相对前窗的均值抬升,用局部噪声尺度归一化”。噪声越大,s 越大,Z 越小,天然抑制误报;真实起跳时 m2−m1 持续为正,Z 快速抬升。检测规则为:Z[k] 首次连续 N 个点超过阈值 T,判定起跳点位于该连续段的第一个点。

窗口长度与阈值的取舍关系

窗口长度 L 决定“灵敏度—延迟”的平衡:L 太小,s 估计不稳,噪声尖峰易触发误报;L 太大,起跳被平均掉,检测延迟增大。阈值 T 决定“误报—漏报”的平衡。下面用同一段合成压力数据(含已知起跳点)演示不同参数组合的表现。

双窗口 Z 统计量检测起跳点(L=12,T=3.0,N=3) 生产压力 p(t) 真实起跳点 前窗 L 后窗 L Z 统计量 T=3.0 检测触发 延迟 Δ L 增大 → 噪声尺度 s 更稳、误报↓,但起跳被平均、延迟↑;T 增大 → 误报↓、漏报↑;N 增大 → 抗瞬时尖峰、延迟↑

可运行的检测实现

下面给出完整可运行的 Python 实现,包含合成数据生成(已知起跳点)、双窗口 Z 检测、参数扫描与延迟/误报统计。数据为教学示例,起跳点位置与噪声水平由代码显式设定,结果可复现。

import numpy as np

def make_pressure(n=600, onset=400, noise=0.05, rise=0.6, seed=0):
    """合成生产压力:基线缓慢递减 + 高斯噪声;onset 后叠加线性上升。"""
    rng = np.random.default_rng(seed)
    t = np.arange(n)
    base = 30.0 - 0.002 * t                      # 正常递减趋势
    p = base + rng.normal(0, noise, n)
    p[onset:] += rise * (1 - np.exp(-(t[onset:] - onset) / 25.0))
    return p

def detect_onset(p, L=12, T=3.0, N=3):
    """双窗口 Z 统计量检测起跳点,返回 (起跳索引, Z 序列)。"""
    n = len(p)
    Z = np.full(n, -np.inf)
    for k in range(L, n - L):
        seg = p[k - L:k + L]
        m1 = p[k - L:k].mean()
        m2 = p[k:k + L].mean()
        s = np.diff(seg).std()
        Z[k] = (m2 - m1) / (s / np.sqrt(L) + 1e-9)
    # 连续 N 点超阈值
    for k in range(L, n - L - N):
        if np.all(Z[k:k + N] > T):
            return k, Z
    return -1, Z

def evaluate(onset_true, onset_det, n):
    """延迟与误报:检测到则延迟=det-true;未检测到记漏报。"""
    if onset_det < 0:
        return None, 1
    delay = onset_det - onset_true
    false_alarm = 1 if delay < -5 else 0   # 明显早于真实起跳视为误报
    return delay, false_alarm

# 参数扫描:不同噪声水平 × 窗口长度
for noise in [0.03, 0.08, 0.15]:
    p = make_pressure(noise=noise, seed=1)
    print(f"noise={noise}")
    for L in [6, 12, 24]:
        det, Z = detect_onset(p, L=L, T=3.0, N=3)
        delay, fa = evaluate(400, det, len(p))
        print(f"  L={L:2d}  det={det:4d}  delay={delay}  false_alarm={fa}")

运行后观察输出:噪声 0.03 时三种窗口都能检出且延迟小;噪声 0.15 时 L=6 易出现误报或抖动,L=24 延迟明显增大。这正说明窗口长度需随噪声水平调整——噪声大时适当增大 L 以稳定 s 估计,同时可略降 T 补偿灵敏度损失。

参数选择与结果判读

噪声水平(示例)推荐 L推荐 TN预期表现
低(σ≈0.03)6–82.5–3.02–3延迟小,误报低
中(σ≈0.08)10–143.0–3.53平衡延迟与误报
高(σ≈0.15)18–263.5–4.03–4延迟增大,误报受控
判读要点:检测触发点应落在真实起跳点之后、压力明显抬升之前;若触发点远早于起跳点,多为噪声尖峰导致的误报,应增大 L 或 T;若迟迟不触发,多为窗口过长把起跳平均掉,应减小 L 或降低 T。
Z 值依赖局部差分标准差 s,若压力曲线存在阶跃式数据缺失或量程切换,s 会被异常放大导致漏报。工程上应先做缺失值插补与量程归一,再进入检测。