This article demonstrates how to use the AnomalyDetector operator, which is capable of detecting anomalous subsequences in a streaming time series.
The AnomalyDetector operator is capable of performing online anomaly detection of a time series. More specifically, the AnomalyDetector operator reports anomalies with the pattern of the incoming time series. This type of operator has many different uses and can be utilized in a number of different industries. One example of where this operator may be useful is in the medical industry. By using this operator in conjunction with monitor patients, medical staff can be alerted immediately to changes in patient vital signs.
The following image was developed using actual output from the AnomalyDetector operator. As the time series was ingested by the operator, the anomaly detection algorithm analyzed the patterns to determine if there were any anomalies. The orange area was reported by the AnomalyDetector operator as being anomalous.
How it works
The AnomalyDetector operator maintains a recent history of the input time series, which is referred to as the reference pattern. Whenever the AnomalyDetector ingests a tuple, that tuple is added to a buffer called the current pattern (the current pattern is essentially the most recent set of data points received). When this occurs, the operator compares the current pattern with the reference pattern. This comparison operation calculates a score that indicates how similar or dissimilar the current pattern is compared with the reference pattern. The higher the score, the more dissimilar the patterns are.
The following example will demonstrate in more detail how the underlying anomaly detection algorithm works.
In this example, I will provide a high-level demonstration of the algorithm that is used by the AnomalyDetection operator. Rather than discuss every possible parameter, I will focus only on those parameters that are necessary to understand the algorithm.
For this example, the following parameter values will be used:
referenceLength: 10 patternLength: 3 patternCount: 5 (default)
The referenceLength parameter specifies the size of the reference pattern.
The patternLength parameter specifies the size of the current pattern.
The patternCount parameter specifies how many times the current pattern will be compared against sub-sequences of the reference pattern.
For this example, I will use the following time series. The red square represents the reference pattern, which has a length of 10 (as defined by the referenceLength parameter). The blue square represents the current pattern, which has a length of 3 (as defined by the patternLength parameter).
The first step is to add a new point to this time series. When the new point is added, the current pattern will be updated to include the new point. (The reference pattern does not get updated until the end, once all of the comparison operations are performed.)
Once the new point has been added, the operator will begin comparing the current pattern with sub-sequences of the reference pattern. The sub-sequences will have a length of 3, which are the same size as the current pattern length (defined by the patternLength parameter). The following image demonstrates what the first sub-sequence look like:
The above image shows that the first sub-sequence spans 3 points (from 1 to 3, inclusive). The anomaly detection algorithm will compare the sub-sequence reference pattern with the current pattern and calculate a score. Once this has completed, the sub-sequence reference pattern will shift one step to the right and another comparison will be done (the number of steps that the sub-sequence shifts can be set using the stepSize parameter). There will be a total of¬† 5 sub-sequences comparisons performed. The number of comparisons performed is specified by the patternCount parameter.
The following images demonstrate the remaining sub-sequence comparisons.
Once all of the compare operations have completed, an aggregated score is calculated. This aggregated score is then compared against the value specified by the confidence parameter. If the calculated score is greater than the confidence parameter, the current pattern is considered to be anomalous and the AnomalyDetector operator will submit a tuple containing information about the anomalous pattern.
The last step is to update the reference pattern to include the new time series point. Once this is done, the process will repeat.
In the previous section, I discussed the underlying algorithm that drives the AnomalyDetector operator. In this section I have provided information about various important aspects of the AnomalyDetector operator. The complete set of documentation for the AnomalyDetector operator can be found on the AnomalyDetector Knowledge Center page.
The AnomalyDetector operator comes with a number of parameters. Details for each of the available parameters can be found on the AnomalyDetector Knowledge Center page. However, there are some important parameters that I want to highlight here.
patternLength – Specifies the length of the ‘current pattern’
referenceLength – The number of tuples to store as part of the ‘reference pattern’
patternCount – The number of subsequence patterns that the current pattern will be compared against
stepSize – Specifies how many steps the sliding window will shift (default value is 1)
confidence – Limits the output to only those sequences that have a score equal to or greater than the specified value
The AnomalyDetector operator analyzes a single, continuous time series. The inputTimeseries parameter must be set to an attribute on the input port with a type of float64.
There are four output functions that can be used to return the information about detected anomalies. These output functions include:
getSubsequence() – Returns a list<float64> that contains the anomalous pattern.
getScore() – Returns the calculated score of the anomalous pattern.
getStartTime() – Returns the start time of the anomalous pattern (can only be used if the inputTimestamp parameter is specified)
getEndTime() – Returns the end time of the anomalous pattern (can only be used if the inputTimestamp parameter is specified)
Sample on GitHub
You will find a working sample on GitHub that contains the AnomalyDetector operator: https://github.com/IBMStreams/samples/tree/master/timeseries/AnomalyDetectorSample
In this sample, the incoming time series represents the number of packets per second that a NIC received, sampled every second over a 3 minute (180 second) period. Here is an example of what the incoming data looks like:
As can be seen from the above, there are 2 obvious anomalies around 60 seconds and 130 seconds. After streaming the data through the AnomalyDetector operator, the following scores (confidence values) were calculated.
From the above chart, we can see that around the same time that the packet count spiked, the score returned by the AnomalyDetector jumps dramatically.
The AnomalyDetector operator is easy to implement and yet powerful in it’s capabilities. The operator is available in the com.ibm.streams.timeseries toolkit packaged with Streams 18.104.22.168 and later.