-
Notifications
You must be signed in to change notification settings - Fork 867
/
skyline_detector.py
51 lines (40 loc) · 1.86 KB
/
skyline_detector.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
from nab.detectors.base import AnomalyDetector
from nab.detectors.skyline.algorithms import (median_absolute_deviation,
first_hour_average,
stddev_from_average,
stddev_from_moving_average,
mean_subtraction_cumulation,
least_squares,
histogram_bins)
class SkylineDetector(AnomalyDetector):
""" Detects anomalies using Etsy Skyline's ensemble of algorithms from
https://github.com/etsy/skyline/blob/master/src/analyzer/algorithms.py.
Each algorithm in the ensemble gives a binary vote for the data record.
The original implementation used a majority voting scheme to classify a record
as anomalous. Here we improve the detector's performance by using the average
of the algorithms' votes as an anomaly score.
"""
def __init__(self, *args, **kwargs):
# Initialize the parent
super(SkylineDetector, self).__init__(*args, **kwargs)
# Store our running history
self.timeseries = []
self.recordCount = 0
self.algorithms = [median_absolute_deviation,
first_hour_average,
stddev_from_average,
stddev_from_moving_average,
mean_subtraction_cumulation,
least_squares,
histogram_bins]
def handleRecord(self, inputData):
"""
Returns a list [anomalyScore].
"""
score = 0.0
inputRow = [inputData["timestamp"], inputData["value"]]
self.timeseries.append(inputRow)
for algo in self.algorithms:
score += algo(self.timeseries)
averageScore = score / (len(self.algorithms) + 1)
return [averageScore]