时间序列异常检测机制的研究

 ADDOPS团队籍鑫璞 360云计算算法

女主宣言运维

本文出自于ADDOPS团队,该文章的做者籍鑫璞主要负责360 HULK云平台运维自动化和智能运维方面的工做。本文提出了一种高效的LVS流量异常检测算法,帮助ops同事更加精准的判断业务流量突增突减等非正常状态。但愿该文章能给你们对异常检测的理解有所启发,后续会有做者对机器学习落地运维创新的系列文章,敬请期待。机器学习

PS:丰富的一线技术、多元化的表现形式,尽在“HULK一线技术杂谈”,点关注哦!ide

前言wordpress

双十一刚过,阿里还有京东就在疯狂地show(秀)他们的技术有多牛逼。无可厚非,两家公司在应对guagngu节的时候都有本身的一套针对不一样场景的策略。试想一下,假如双十一那每天猫的主页访问不了,那马爸爸不得损失好多个亿。为了防止这样的状况出现,除了疯狂扩容之外,一套理想的异常检测机制也是很是很是重要的。学习


异常检测的场景不少,例如硬件的故障检测、流量的异常点的检测等场景。这篇博客咱们针对的是时间序列的异常检测。时间序列异常的检测算法有不少,业界比较流行的好比普通的统计学习方法--3σ原则,它利用检测点偏移量来检测出异常。好比普通的回归方法,用曲线拟合方法来检测新的节点和拟合曲线的偏离程度,甚至有人讲CNN和RNN技术应用到异常点的检测。云计算


经过普通的阈值来检测lvs流量异常的方法效果比较差,本篇文章提出了一种新的检测算法,下面将重点介绍咱们在实践过程当中的经验。spa


1.net

数据分析3d

获取过去7天的lvs流量的数据,咱们能够大体将趋势分为两种:


一种是以下图的具备周期性的数据,这种状况更多须要考虑周期性给数据带来的影响。

图片


而另外一种以下图的随机的数据,不具备周期性,这种状况须要采用和周期性不同的策略来检测。

图片


2

检测机制的研究

因为曲线就有周期性和非周期性的两种趋势,因此咱们的检测机制须要可以处理两种方式。


下面咱们将详细介绍每一个算法。


 

算法

短时间环比(SS)


对于时间序列(是指将同一统计指标的数值按其发生的时间前后顺序排列而成的数列)来讲,T时刻的数值对于T-1时刻有很强的依赖性。好比流量在8:00不少,在8:01时刻的几率是很大的,可是若是07:01时刻对于8:01时刻影响不是很大。


首先,咱们可使用最近时间窗口(T)内的数据遵循某种趋势的现象来作文章。好比咱们将T设置为7,则咱们取检测值(now_value)和过去7个(记为i)点进行比较,若是大于阈值咱们将count加1,若是count超过咱们设置的count_num,则认为该点是异常点。image.png

上面的公式涉及到threshold和count_num两个参数,threshold如何获取咱们将在下节进行介绍,而count_num能够根据的需求进行设置,好比对异常敏感,能够设置count_num小一些,而若是对异常不敏感,能够将count_num设置的大一些。


动态阈值


业界关于动态阈值设置的方法有不少,今天介绍一种针对咱们lvs流量异常检测的阈值设置方法。一般阈值设置方法会参考过去一段时间内的均值、最大值以及最小值,咱们也一样应用此方法。取过去一段时间(好比T窗口)的平均值、最大值以及最小值,而后取max-avg和avg-min的最小值。之因此取最小值的缘由是让筛选条件设置的宽松一些,让更多的值经过此条件,减小一些漏报的事件。image.png


长期环比(LS)


上面短时间环比参考的是短时间内的数据,而仅仅有短时间内的数据是不够的,咱们还须要参考更长时间内数据的整体走势。


一般使用一条曲线对该趋势进行拟合来反应曲线的走势,若是新的数据打破了这种趋势,使曲线变得不平滑,则该点就出现了异常。曲线拟合的方法有不少,好比回归、moving average 等等。在这篇文章中,咱们使用EWMA,即指数权重移动平均方法来拟合曲线。在EWMA种,下一点的平均值是由上一点的平均值,加上当前点的实际值修正而来。对于每个EWMA值,每一个数据的权重是不同的,最近的数据将拥有越高的权重。


有了平均值以后,咱们就可使用3-sigma理论来判断新的input是否超过了容忍范围。比较实际的值是否超出了这个范围就能够知道是否能够告警了。

expAverage = pd.stats.moments.ewma(data, com=50) 

stdDev = pd.stats.moments.ewmstd(data, com=50)

if abs(data.values[-1] - expAverage.values[-1]) > 3 * stdDev.values[-1] :

    print "异常"


同比(chain)


不少监控项都具备必定的周期性,其中以一天为周期的状况比较常见,好比lvs流量在早上4点最低,而在晚上11点最高。为了将监控项的周期性考虑进去,咱们选取了某个监控项过去14天的数据。对于某个时刻,将获得14个点能够做为参考值,咱们记为xi,其中i=1,...,14。


咱们先考虑静态阈值的方法来判断input是否异常(突增和突减)。若是input比过去14天同一时刻的最小值乘以一个阈值还小,就会认为该输入为异常点(突减);而若是input 比过去14天同一时刻的最大值乘以一个阈值还大,就会认为该输入为异常点(突增)。

if new_value > max(过去14天同一时刻的值) *  max_threshold:

    print "突增"

if new_value < min(过去14天同一时刻的值) *  min_threshold:

    print "突减"

静态阈值的方法是根据历史经验得出的值,实际中如何给max_threshold和min_threshold是一个须要讨论的话题。根据目前动态阈值的经验规则来讲,取平均值是一个比较好的思路。


同比振幅(CA)


同比的方法遇到下图的现象就不能检测出异常。好比今天是11.18日,过去14天的历史曲线必然会比今天的曲线低不少。那么今天出了一个小故障,曲线下跌了,相对于过去14天的曲线仍然是高不少的。这样的故障使用方法二就检测不出来,那么咱们将如何改进咱们的方法呢?一个直觉的说法是,两个曲线虽然不同高,可是“长得差很少”。那么怎么利用这种“长得差很少”呢?那就是振幅了。


怎么计算t时刻的振幅呢? 咱们使用x(t) – x(t-1) 再除以 x(t-1)来表示振幅。举个例子,例如t时刻的流量为900bit,t-1时刻的是1000bit,那么能够计算出掉线人数是10%。若是参考过去14天的数据,咱们会获得14个振幅值。使用14个振幅的绝对值做为标准,若是m时刻的振幅[m(t) – m(t-1)]/m(t-1)大于amplitudethreshold而且m时刻的振幅大于0,则咱们认为该时刻发生突增,而若是m时刻的振幅大于amplitudethreshold而且m时刻的振幅小于0,则认为该时刻发生突减。image.png


 

算法组合

上面介绍了四种方法,这四种方法里面,SS和LS是针对非周期性数据的验证方法,而chain和CA是针对周期性数据的验证方法。那这四种方法应该如何选择和使用呢?下面咱们介绍两种使用方法:


1、根据周期性的不一样来选择合适的方法。这种方法须要首先验证序列是否具备周期性,若是具备周期性则进入左边分支的检测方法,若是没有周期性,则选择进入右分支的检测方法。image.png

上面涉及到了如何检测数据周期的问题,可使用差分的方法来检测数据是否具备周期性。好比取最近两天的数据来作差分,若是是周期数据,差分后就能够消除波动,而后结合方差阈值判断的判断方法来肯定数据的周期性。固然,若是数据波动范围比较大,能够在差分以前先对数据进行归一化(好比z-score)。


2、不区分周期性,直接根据“少数服从多数”的方法来去检测,这种方法比较好理解,在此就不说明了。image.png


3

总结

这篇文章介绍了咱们在lvs异常检测中使用的方法,也许这些方法还不够解决全部的场景,你还须要在此基础上去不断丰富算法,才能达到比较好的效果。所谓,理论结合实际,具体的问题须要具体的分析,才能将理论应用于实践。

参考文献:


1.https://jiroujuan.wordpress.com/2013/10/09/skyline-anomalous-detect-algorithms/ 

2.http://chuansong.me/n/2032667

3.http://blog.csdn.net/g2V13ah/article/details/78474370