|在时间序列异常检测场景中,“节假日效应”是一个让很多人头疼的问题。本文分为上下俩篇,上篇主要是解析清华的论文Automatic and Generic Periodic Adaptation for KPI Anomaly Detection, 从中提取一些可借鉴的思路;下文主要是在腾讯业务的代码实践篇,在现有metis智能检测的基础上,加入节假日效应的解决方案。
1. 背景介绍:
在时间序列异常检测场景中,“节假日效应”是一个让很多人头疼的问题。所谓节假日效应,就是指在节假日期间,甚至前后一俩天,它的时间序列的走势和平常的时间序列走势有着很明显的区别。 尽管曲线有着明显区别的走势,但是业务往往是正常的。
同时我们也都知道,节假日还往往伴随着“调休”,即节假日的前后一周的周末,可能会变成工作日正常上班。 这种“节假日效应”引起的曲线不一样问题,如果不能很好的解决,会导致在节假日前后会有爆发式的告警出来。
在实际解决“节假日效应”问题的过程中,可能会遇到以下一些问题:
- 周期性的多样性:不同指标,它的周期是完全不一样的,有些可能是每天都差不多;有些则可能分为工作日和休息日;有些则可能展现出更多的周期特征来。
- KPI 数量巨大:这个通常来说都是智能运维领域中的常见问题;
- 周期的漂移:一般来说,通过时间序列的走势我们只能够看出一个大致的变化,但是具体到细节的话,周期是存在一定的波动的。例如不一定恰好是 7 天,有可能是 7 天加减 30 分钟之类的周期。这个跟业务的具体场景有关系,也跟当时的实际情况有关。
- 节假日差别:不同节假日的业务曲线,可能也不是一致的。 一方面是不同节假日的性质不一样,另外一方面节假日的时间长度也不一样。比如春节是7天,大家在家会有更多的时间来玩游戏,对应的游戏类业务的流量可能呈现爆涨状态;而双11,更多的是电商类业务的流量暴涨。
为了解决这种“节假日效应”问题,我们查看了业界各种方法,发现清华大学的 Netman 实验室的一篇论文可以给我们提供一些思路。
这篇论文的标题是《Automatic and Generic Periodic Adaptation for KPI Anomaly Detection》。在该论文文中,所用的时间序列是各种各样的业务指标的,包括搜索引擎,网上的应用商店,社交网络数据等等。作者们针对 KPI(Key Performance Indicator)做了时间序列异常检测,并且发明了一种方法来避免节假日效应的问题。该论文结合日期,对时间序列中的工作日(work days),休息日(off days),节假日(festival),和商务活动(business activities)做了区分。 按照这种区分再结合每天的时间序列曲线进行聚类,可以按照当前在本周是第几天(day of week)和在本月是第几天(day of month)的离线划分,将当前实时检测的时间序列划分到对应的类别中,从而选则对应的模型进行检测。通过日期来划分时间序列,并再次进行同类型的时间序列段的组合从而避免了不同类型周期之间互相的干扰, 在一定的程度上解决了“节假日效应”的问题。
2. 总结与讨论:
2.1. 这篇论文的核心思想是:
从上图可以看到 Period 的核心思想。在本文使用的数据中,时间序列的长度较长,一般来说都是好几个月到半年不等,甚至更长的时间。对于一条时间序列(a given KPI),可以将它的历史数据(historical data)进行按天切分,获得多个子序列(sub KPIs)。对于这多个子序列,需要进行聚类以得到不同类别。或者按照日历直接把时间序列的工作日(work day),休息日(off day),春节(spring festival)序列进行切分,将工作日放在一起,休息日放在一起,春节放在一起。把这些子序列进行拼接就可以得到三条时间序列数据,分别是原时间序列的工作日序列(work day subsequence),休息日序列(off day subsequence),春节序列(spring festival subsequence)。然后分别对着三条时间序列训练一个异常检测的模型(例如 Holt-Winters 算法,简写为 HW)。对于新来的时间序列,可以根据当日具体的日期(工作日,休息日或者春节)放入相应的模型进行异常检测,从而进一步地得到最终的结果。
总结来说:
- 离线:结合日历,把每天的日期作为特征划分时间序列到子序列。 再结合时间序列聚类算法,进行聚类。
- 相同类型的时间序列进行组合,形成完整的时间序列,并迭代优化对应模型的参数。
- 在线:实时传入的待检测时间序列,通过日期等特征,选择它对应的类别,通过对应的检测模型进行检测。
- 通过上述操作,可以把不同周期的划分到对应的类别中,从而互相不会影响。
2.2. 整体模型
Period 的整体架构如上图所示,主要包括离线进行周期性验证分类 在线选择对应的类别进行检测俩个部分:
- 离线周期性检测(offline periodicity detection):结合日期特征,将每一条时间序列按天切分成一段段的子序列; 再结合时间序列聚类算法,进行聚类。
- 在线适应性异常检测(online anomaly detection adaptation):新来的时间序列会根据其具体的日期,分入相应的类,然后用该类的检测模型来进行异常检测。
而在具体的实验中,则需要考虑以下细节:
- 聚类算法的选择:
常见的聚类算法像k-means, k-medoids,。 当时这几种都需要事先设定聚类数k。 在无先验经验的情况下,对时间序列聚类是很难事先定义出k的。(有些业务指标也可以通过经验,或观察一段长时间的时间序列,人工设定聚类数量。)
而像DBSCAN, one-pass-clustering等聚类算法,则不需要事先设定聚类数k,更加适合不知道多少类别的时间序列聚类问题。
- 曲线相似度度量中的“漂移问题”
由于在实际的指标曲线中,可能存在一定的漂移,如上图。每天都会有一个高峰,不过时间点10-30是12点左右,10-31号则是10点左右,11-1号则是下午俩点左右。 为了解决这种漂移,可以考虑在时间窗口内去平移子序列,去计算得到最大的相似值。
计算公式如下。
- 聚类的命名算法
通过相似性度量后,我们可以将时间序列进行聚类,然后通过上述算法也可以对每一个聚类的结果进行命名。
2.3. 举例来说:
2.3.1. 案例一
指标A包括了俩种类型,一种是工作日,一种是休息日。每天的指标进来,通过日期可以识别出是工作日还是休息日,然后选择对应离线训练好的模型进行检测。这样来看,工作日的模型,全部是针对工作日的时间序列训练而得,幅度也更加一致,不容易受到休息日幅度降低的影响,从而可以得到更好的F1-score表现。
2.3.2. 案例二
另外一个例子是指标F,可以看到,可以分成3类:工作日,休息日,国庆节。
针对工作日和休息日,和指标A类似。 国庆节则可以单独设定检测模型/策略。
通过这种日期特征,每天都可以选择更加合适的模型,一方面避免了统一化的模型在不同日期表现差别的问题,另外一方面也可以针对节假日/特殊活动日进行单独化的检测处理。
3. 回归腾讯业务
腾讯目前很多业务都具有明显的周期特征,特别是发展相对比较稳定的业务,如下图,是某业务的流量指标和cpu指标:
可以看到,流量指标几乎在每个工作日的夜晚,都会有一个峰值出现。而周六/周天则没有峰值。cpu则是每天都会在晚上有一个峰值,不过工作日/休息日的峰值幅度不一样。
对比目前metis采用的同环比特征(同比:和7天前比;环比:和昨天比),metis的模型特征目前存在俩个问题:
- 比如周六,同环比存在着比较大的差异:对比周五,周期性强的业务有一定的差别;对比上周六,则可能比较相似。这其实会导致对比周五的效果比较差。
- metis目前没办法很好的识别节假日效应。因此每当节假日发生,都会导致大量的告警。(这里的告警很多可能是无效的,虽然告警出来也说的通)
- 而通过细分每一天到每一天的模型:例如工作日,休息日,节假日,特殊日期等,一方面可以帮助metis解决节假日问题,另外一方面也可以帮助metis的同环比特征更好的进行对比。
Reference:
- https://ieeexplore.ieee.org/document/8723601
- https://zr9558.com/2020/05/05/tsanomalydetectionholiday/
- https://vectorf.github.io/2017/03/14/20170314-Prophet之使用篇(四)/
- https://www.cnblogs.com/pinard/p/6164214.html
- https://towardsdatascience.com/understanding-k-means-k-means-and-k-medoids-clustering-algorithms-ad9c9fbf47ca
- https://cloud.tencent.com/developer/article/1724034