算法原理、命名与用途
1. 算法原理
该算法MDAM全称为均值漂移累积监测算法(Mean Drift Accumulation Monitor),核心原理是通过统计数据序列中超出基准值偏移范围的样本比例,识别均值突变:
- 设定基准值μ、允许偏移量p,构建正常区间[μ-p, μ+p];
- 统计超出区间的样本:上偏移(>μ+p)记为cnt_up,下偏移(<μ-p)记为cnt_down;
- 计算异常比例(up_ratio = cnt_up/总样本数、down_ratio = cnt_down/总样本数),当任一比例超过阈值k时,判定为均值突变(正数表示上突,负数表示下突)。
2. 算法命名
规范命名为MDAM(Mean Drift Accumulation Monitor,均值漂移累积监测算法),既体现“均值漂移”的检测目标,也突出“累积统计”的核心逻辑,避免与现有算法混淆。
3. 主要用途
MDAM适用于需快速检测数据序列均值突变的场景,典型用途包括:
- 工业监控:生产线温度、压力等指标的异常波动检测;
- 网络安全:识别DDoS攻击等流量突增/突减异常;
- 医疗监测:生命体征(如心率、血压)的异常漂移预警;
- 金融风控:交易金额、频次的突变模式识别;
- 环境监测:空气质量、水质指标的均值突变检测。
Python详细函数示例(优化版)
以下是结合向量化计算和动态基准更新的优化函数,支持批量数据检测和抗干扰参数调整:
import numpy as np
from typing import Union, Tuple, Optional
def mdam_detect(
data: Union[list, np.ndarray],
base_window: int, # 用于计算基准值μ的历史数据窗口大小
p: float, # 允许偏移量
k: float = 0.8, # 异常比例阈值(0-1)
detect_window: int = 100 # 每次检测的滑动窗口大小
) -> Tuple[np.ndarray, np.ndarray]:
"""
MDAM算法:检测数据序列中的均值突变
参数:
data: 输入数据序列(list或numpy数组)
base_window: 计算基准值μ的历史窗口大小(如前100个数据)
p: 允许的偏移量(如2倍标准差)
k: 异常比例阈值(默认0.8,即80%数据超范围则判定突变)
detect_window: 滑动检测窗口大小(每次检测最近N个数据)
返回:
突变标记数组:1表示上突,-1表示下突,0表示无突变
异常比例数组:对应每个检测窗口的上突/下突比例(正数为上,负数为下)
"""
# 数据预处理
data = np.asarray(data, dtype=np.float64)
if len(data) < base_window + detect_window:
raise ValueError("数据长度需大于基准窗口+检测窗口")
# 初始化结果数组
n_windows = len(data) - base_window - detect_window + 1
突变标记 = np.zeros(n_windows, dtype=int)
异常比例 = np.zeros(n_windows, dtype=np.float64)
for i in range(n_windows):
# 动态计算基准值μ(当前窗口前的base_window个数据的均值)
base_data = data[i : i + base_window]
mu = np.mean(base_data)
# 待检测窗口数据
detect_data = data[i + base_window : i + base_window + detect_window]
# 计算上/下偏移比例
up_mask = detect_data > (mu + p)
down_mask = detect_data < (mu - p)
cnt_up = np.sum(up_mask)
cnt_down = np.sum(down_mask)
total = len(detect_data)
up_ratio = cnt_up / total
down_ratio = cnt_down / total
# 判定突变
if up_ratio > k:
突变标记[i] = 1
异常比例[i] = round(up_ratio, 3)
elif down_ratio > k:
突变标记[i] = -1
异常比例[i] = -round(down_ratio, 3)
else:
突变标记[i] = 0
异常比例[i] = 0.0
return 突变标记, 异常比例
# 示例:检测模拟数据中的突变
if __name__ == "__main__":
# 生成模拟数据:前500正常,中间300上突,后200下突
np.random.seed(42)
normal_data = np.random.normal(loc=10, scale=1, size=500) # 基准均值10
up_data = np.random.normal(loc=15, scale=1, size=300) # 上突(均值15)
down_data = np.random.normal(loc=5, scale=1, size=200) # 下突(均值5)
data = np.concatenate([normal_data, up_data, down_data])
# 调用算法检测(基准窗口100,检测窗口50,偏移量p=3,阈值k=0.7)
突变标记, 异常比例 = mdam_detect(
data=data,
base_window=100,
p=3,
k=0.7,
detect_window=50
)
# 输出结果(打印前20个和后20个窗口的检测结果)
print("突变标记(1=上突,-1=下突,0=正常):")
print(突变标记[:20], "...", 突变标记[-20:])
print("\n异常比例:")
print(异常比例[:20], "...", 异常比例[-20:])
与现有集中趋势检测算法的对比
特性 | MDAM算法 | 传统集中趋势检测(如CUSUM、Mann-Kendall) |
---|---|---|
检测目标 | 均值突变(离散、突发) | 微小漂移(CUSUM)、趋势变化(Mann-Kendall) |
参数复杂度 | 低(3个核心参数) | 中高(CUSUM需2个阈值,Mann-Kendall需多个统计量) |
计算效率 | O(n)(支持向量化) | CUSUM为O(n),Mann-Kendall为O(n²) |
方向敏感性 | 支持(区分上突/下突) | CUSUM支持,Mann-Kendall不直接支持 |
抗噪性 | 强(比例阈值过滤偶发异常) | 较弱(易受连续小波动干扰) |
实时性 | 优秀(适合嵌入式/实时系统) | 良好(CUSUM)/较差(Mann-Kendall) |
MDAM的核心优势在于参数简单、计算高效、抗噪性强,尤其适合需要快速响应突发均值突变的场景,弥补了传统算法在实时性和抗干扰性上的不足。