import numpy as np
from dtaianomaly import utils
from dtaianomaly.anomaly_detection._BaseDetector import BaseDetector, Supervision
from dtaianomaly.type_validation import BoolAttribute
__all__ = ["SquaredDifference"]
[docs]
class SquaredDifference(BaseDetector):
"""
Compute anomaly scores based on the squared difference.
Baseline anomaly detector, assings an anomaly score as the squared
difference of an observation and the previous observation. Formally,
the anomaly score :math:`s_i` for observation :math:`x_i` equals
:math:`s_i = (x_i - x_{i-1})^2`.
Parameters
----------
square_errors : bool, default=True
If the differences should be squared. If False, this detector equals the
absolute difference.
Examples
--------
>>> from dtaianomaly.anomaly_detection import SquaredDifference
>>> from dtaianomaly.data import demonstration_time_series
>>> x, y = demonstration_time_series()
>>> baseline = SquaredDifference().fit(x)
>>> baseline.decision_function(x)
array([0.00779346, 0.00779346, 0.00260361, ..., 0.00286662, 0.05578398,
0.02683475]...)
"""
square_errors: bool
attribute_validation = {"square_errors": BoolAttribute()}
def __init__(self, square_errors: bool = True):
super().__init__(Supervision.UNSUPERVISED)
self.square_errors = square_errors
def _fit(self, X: np.ndarray, y: np.ndarray = None, **kwargs) -> None:
"""Requires no fitting."""
def _decision_function(self, X: np.ndarray) -> np.array:
# Check if the given dataset is univariate
if not utils.is_univariate(X):
raise ValueError("Input must be univariate!")
decision_scores = np.empty(shape=X.shape[0])
decision_scores[1:] = np.abs(np.diff(X.squeeze()))
decision_scores[0] = decision_scores[1] # Padding
if self.square_errors:
decision_scores = np.square(decision_scores)
return decision_scores