【时间序列异常检测算法】——传统异常检测算法介绍及代码实现

背景

前面博客讲述了正常值组成的时间序列如何预测t时刻的值,是时序预测任务;
这里讲述的是包含有异常值的时间序列如何判定哪个时刻发生了异常,是时序异常检测任务。
同比:本期与同期做对比。
环比:本期与上期做对比。
异常主要包括:

  1. 数据突变异常:数据在某个时刻或短时间段内,突升/突降。使用环比检测。
  2. 周期性异常:正常情况下,不同周期间的数据变化趋势是一致的,异常是某周期时间段内趋势和其他周期内趋势不同。使用同比检测。

归纳为三个场景:

  1. 场景一:数据无规律波动,但正常基本在一个较小的波动范围内,典型的场景就是拒绝数监控,通常我们会按照拒绝数的常态波动范围设定一个或多个恒定阈值,超过阈值即报警。

  2. 场景二:数据的长期波动幅度较大,但正常情况下短期的波动幅度较小,体现在图像上是一根比较光滑的曲线,不应该有突然性的上涨或者下跌。典型的场景包括订单、流水。这类场景监控的主要思想就是环比附近的数据,检查是否存在突然的大幅上涨或下跌(差值是否超出阈值)。

  3. 场景三:数据有规律地周期性波动,比如广告收入或搜索流量等。检测这类数据的方法是与历史的周期数据作同比,超出阈值发现异常。

算法介绍

单参数恒定阈值

y t ∈ [ t h 1 , t h 2 ] y_t\in [th1,th2] yt[th1,th2]
对时序参数y判定是否在范围内,超出即报警,阈值选取难,选宽会漏报,选窄会虚警,需要衡量两矛盾的指标量,选择合适的阈值;易受毛刺(野值、噪点、坏值)影响,虚警高。

单参数均值阈值

设定时间窗口L,计算时间窗口内 y t o r ∣ y t ∣ y_t or |y_t| ytoryt的均值
1 / L ∗ Σ L y t   o r   1 / L ∗ Σ L ∣ y t ∣ ∈ [ t h 1 , t h 2 ] 1/L*\Sigma_Ly_t\ or\ 1/L*\Sigma_L|y_t| \in [th1,th2] 1/LΣLyt or 1/LΣLyt[th1,th2]
抗较均匀的噪声干扰,不受个别坏值的影响,但如果噪点赋值过大则也会触发虚警。

单参数累积/积分阈值

设定时间窗口L,计算时间窗口内 y t o r ∣ y t ∣ y_t or |y_t| ytoryt积分(面积)
∫ L y t d t   o r ∫ L ∣ y t ∣ d t ∈ [ t h 1 , t h 2 ] \int_Ly_tdt\ or \int_L|y_t|dt \in [th1,th2] Lytdt orLytdt[th1,th2]
可避免毛刺个别坏值的影响,可靠性更高
代码实现可通过矩形条逼近近似计算。

单参数均值漂移检测

变换
设定时间窗口w,计算上个窗口内的均值与当前窗口内的均值的比值,将对原时序的异常检测变换到了r空间中,检测r是否超限。
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第1张图片
适用于突变持续时间较长的情况,不适用于个别点突变。

单参数统计分布检测

若时序数据符合某统计分布,则计算均值和方差:
变换
将对原时序的异常检测变换到了z空间中,检测z是否超限。异常的数据不符合该统计分布规律,所以z值就会突变,如果原时序中是个别点异常,则变换到z空间后也为个别点异常;若是持续性异常,则变换后也为持续性异常(连续的N个点均异常)。

NOTE:算法模型参数不是一成不变的,在不同时段如工作日和休假日、白天和晚上的参数都不同,所以参数配置成本非常高,算法和参数需要定期维护。

代码实现

# 参数设定
L = 10#初始化L 初值L会影响最后的结果
num = 100#tsd个数
# TSD数据集构造
t = np.linspace(0,10,num)
y = 2*t + np.random.rand(len(t))
# abnormal data
rand_start = int(num*(np.random.rand()*0.3+0.2))
y[rand_start:rand_start+num//10] = y[rand_start]*2#异常数据是原来数据的两倍
# 原始时序数据
plt.figure(figsize=(16, 7))
plt.plot(y)
plt.title("Raw TSD")
plt.show()
# calc area
def area(yt_window):
    s = [v*1 for v in yt_window]
    return np.sum(s)
area_list = []
for i in range(num-L):
    area_list.append(area(y[i:i+L]))
plt.plot(area_list)
plt.title("Area TSD")
plt.show()

执行结果
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第2张图片
计算积分后的变换空间:
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第3张图片
如果再次变换:
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第4张图片
所以变换一次即可,且能较好的体现出异常点处。
考虑到有趋势因素在,不能直接使用阈值,所以求差分:
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第5张图片
原始数据一阶差分后即可进行环比的恒定阈值检测,再做积分变换意义不大:
【时间序列异常检测算法】——传统异常检测算法介绍及代码实现_第6张图片

参考

CSDN博客

你可能感兴趣的:(自研,算法,python,人工智能,机器学习,时序模型)