09_Geoist之连续时间序列分析模块2
内容摘要:上一节介绍了Geoist的Snoopy模块的时间序列分析基本功能,有了这些还不够,如果数据中有了异常,期望自动检测出来,那还需要有异常检测算法。今天我们继续介绍Snoopy支持的时间序列分析数据异常检测功能。
1、异常检测
先来看什么是异常检测?
所谓异常检测就是发现与大部分对象不同的对象,其实就是发现离群点(Outliers)。异常检测有时也称偏差检测。异常对象是相对罕见的。
在实际应用中,异常检测技术有很多用武之地:
- 欺诈检测:主要通过检测异常行为来检测是否为盗刷他人信用卡。
- 入侵检测:检测入侵计算机系统的行为
- 医疗领域:检测人的健康是否异常
2、常用算法分类
从学术角度,异常监测算法可以分为以下四大类:
Density-Based Approaches
- RKDE: Robust Kernel Density Estimation (Kim & Scott, 2008)
- EGGM: Ensemble Gaussian Mixture Model
Quantile-Based Methods
- OCSVM: One-class SVM (Schoelkopf, et al., 1999)
- SVDD: Support Vector Data Description (Tax&Duin, 2004)
Neighbor-Based Methods
- LOF: Local Outlier Factor (Breunig, et al., 2000)
- ABOD: kNN Angle-Based Outlier Detector (Kriegel, et al., 2008)
Projection-Based Methods
- IFOR: Isolation Forest (Liu, et al., 2008)
- LODA: Lightweight Online Detector of Anomalies (Pevny, 2016)
3、Snoopy的异常检测算法
Geoist的异常检测功能,来源于Linkedin开源的Luminol异常检测算法。Luminol是一个轻量级的用于时间序列数据分析的Python异常检测算法库。
目前,Snoopy模块支持的两个主要功能是异常检测和相关性分析,可用来调查异常的可能原因。
-
对一个时间序列可以,可以检测数据是否包含异常,并返回一个发生异常的时间窗口。当一个异常达到其严重程度的时间戳,以及一个表示与时间序列中的其他异常相比严重程度的评分。
-
给出两个时间序列,帮助找出它们的相关系数。
Snoopy同时也是完全可配置的,可以扩展异常检测或相关的特定算法。
此外,该库不依赖于时间序列值上的任何预定义阈值。相反,它为每个数据点分配一个异常分数,并使用该分数识别异常。
通过使用该模块,可以为建立一个异常处理逻辑任务流程。例如,假设有一个网络延迟的峰值:
- 异常检测发现网络延迟时间序列中的峰值
- 获取峰值的异常周期,并在同一时间范围内与其他系统指标(GC、IO、CPU等)进行关联获得一个相关指标的排序列表。
在该模块基础上,可以容易实现自动化,也可以作为未来工作的基础。
下面我们就简单看看如何使用:
from geoist.snoopy.anomaly_detector import AnomalyDetector
ts = dict(zip(range(len(data)),data['despiked'].values))
my_detector = AnomalyDetector(ts)
score = my_detector.get_all_scores()
fig = plt.figure(figsize=(15,9))
ax = fig.add_subplot(211)
data.plot(ax=ax,y=['despiked'])
ax = fig.add_subplot(212)
ax.plot(score.timestamps,score.values)
上述代码中,需要注意的是Snoopy要求的TS序列格式为字典类型,因此,对于上一节课的数据,先要包装成要给dict,方法为:
ts = dict(zip(range(len(data)),data['despiked'].values))
对于预处理完成后的数据,检测结果如图1所示,默认的算法可以对一个异常曲线给出实时异常评分,设定一个阈值后,就可以自动判断异常。
图1 异常检测识别结果4、算法分析
要进行异常检测,首先要回答什么是异常,如果我们可以通过重复观测得到一个曲线Baseline,那么偏离这个Baseline一段时间后,就可以认为出现了异常,如图2所示。
图2 Baseline算法在实际情况下,可以根据如Page加载时间,Traffic等多种参数,通过与Baseline值对比,联合判断是否出现了网络异常状况,如图3所示。
图3 根据多个指标判断Baseline的偏离程度具体的实现代码如下:
from geoist.snoopy.anomaly_detector import AnomalyDetector
ts = dict(zip(range(len(data)),data['despiked'].values))
window_size = 10
center = False
data['ma'] = data['detrend'].rolling(window=window_size,center=center,min_periods=1).mean()
tsb = dict(zip(range(len(data)),data['ma'].values))
# anomaly baseline
algorithm_params = {'percent_threshold_upper': 20,
'offset': 20000,
'scan_window': 24,
'confidence': 0.01}
my_detector = AnomalyDetector(ts, baseline_time_series = tsb, algorithm_name = 'sign_test',
algorithm_params = algorithm_params)
score = my_detector.get_all_scores()
fig = plt.figure(figsize=(15,12))
ax = fig.add_subplot(211)
ax.plot(data['despiked'].dropna().values)
ax.plot(data['ma'].dropna().values)
ax = fig.add_subplot(212)
ax.plot(score.timestamps,score.values)
上述代码里面,算法选择为“sign_test”,并设置了baseline曲线为tsb,算法参数设计参数详见algorithm_params。效果如图4所示。当蓝色曲线,相比参考的橙色baseline超过设定的offset阈值和percent_threshold_upper参数后,开始报警。
图4Snoopy的异常检测算法默认为“bitmap_detector”,之外除了“sign_test”还支持“diff_percent_threshold”,“exp_avg_detector”等,具体应用细节,感兴趣的朋友们,可以参考源代码。
一句话总结:从应用角度,可调参数越少的异常检测算法往往越好用。根据实际问题设计异常检测算法是应用的关键,在地震前兆监测领域,如何设计自动化的检测算法,这个问题就留给读者们继续来深入研究吧!