1 笨笨的孩子慢慢学stay hungry stay foolish 2 学习,思考,实践,改变

0%

20191210Skyline源码阅读

1 基类结构

首先看异常检测基类base.py,所有检测器都是由它继承而来:

1,init() :初始化dataSet,probationaryPercent 数据的最初一部分数据不做测试。inputMin, inputMax初始化最大最小值。

2,initialize():多进程问题。进程池pool(它默认调用的是CPU的核数)

3,handleRecord(): 返回每一个时间点的异常分数值,Returns a list [anomalyScore, *]。这个函数子类必须继承。

4,getAdditionalHeaders():如HTM检测器里会添加’anomalyscore’ , ‘rawscore’。添加并返回列名的,run函数中调用它拼接最后返回的dataframe。

5,detectDataSet(): 在运行给定检测器的每个检测器进程中调用的函数。参数 (i, detectorInstance, detectorName, labels, outputDir, relativePath) = args,主要是创建保存文件的路径,调用detectorInstance.initialize(),results = detectorInstance.run()

6,run():为整个dataSet打分并返回结果(dataframe格式)

2 Etsy的Skyline算法

继承异常检测器基类。另外它的算法是根据几个小算法各自的评分进行平均投票得到。

1
2
3
4
5
6
7
self.algorithms =   [median_absolute_deviation,
first_hour_average,
stddev_from_average,
stddev_from_moving_average,
mean_subtraction_cumulation,
least_squares,
histogram_bins]
median_absolute_deviation

计算数据的中位数,偏差 = 每个值-中位数,得到偏差中位数

MAD对数据集中的异常值比标准偏差更具弹性。在标准偏差中,与均值的距离的平方,较大的异常值会影响更大。可以通过判断一个点的偏差是否过于偏离MAD来判断异常,此处是如果偏差6倍大于中位数,则判断为异常。

first_hour_average

上一天的这个时间段1h的均值是$mean$,标准差是$std$,如果$|X_t - mean| > 3 * std$ 则是异常。

stddev_from_average

值减去移动平均值大于平均值的三个标准偏差则为异常。

stddev_from_moving_average

值减去指数加权移动平均值大于平均值的三个标准偏差则为异常。

expAvg = series.ewm().mean()

stdDev = series.ewm().std()

mean_subtraction_cumulation

从每个数据源点减去过去历史平均值之后,如果该序列中下一个数据点的值比累积项中的三个标准差远,则该时间序列是异常的。

least_squares
1
2
3
4
5
6
7
8
#X——代表时间 timestamp,Y——代表 value
results = np.linalg.lstsq(A, Y)
residual = results[1] #残差
m, c = np.linalg.lstsq(A, Y)[0] #斜率与截距
for i, value in enumerate(y):
projected = m * X[i] + c
error = value - projected
errors.append(error)

最后点投影到最小二乘上误差大于所有误差的std的3sigma时,判断为异常。

histogram_bins

最后时间点的值落入带有少于threshold个其他数据点的直方图bin中,则时间序列是异常的。