Source code for darts.ad.scorers.norm_scorer

"""
Norm Scorer
-----------

Norm anomaly score (of given order) [1]_.

References
----------
.. [1] https://en.wikipedia.org/wiki/Norm_(mathematics)
"""

import numpy as np

from darts.ad.scorers.scorers import NonFittableAnomalyScorer
from darts.logging import raise_if_not
from darts.timeseries import TimeSeries


[docs]class NormScorer(NonFittableAnomalyScorer): def __init__(self, ord=None, component_wise: bool = False) -> None: """ Returns the elementwise norm of a given order between two series' values. If `component_wise` is False, the norm is computed between vectors made of the series' components (one norm per timestamp). If `component_wise` is True, for any `ord` this effectively amounts to computing the absolute value of the difference. The scoring function expects two series. If the two series are multivariate of width `w`: * if `component_wise` is set to False: it returns a univariate series (width=1). * if `component_wise` is set to True: it returns a multivariate series of width `w`. If the two series are univariate, it returns a univariate series regardless of the parameter `component_wise`. Parameters ---------- ord Order of the norm. Options are listed under 'Notes' at: <https://numpy.org/doc/stable/reference/generated/numpy.linalg.norm.html>. Default: None component_wise Whether to compare components of the two series in isolation (True), or jointly (False). Default: False """ raise_if_not( type(component_wise) is bool, # noqa: E721 f"`component_wise` must be Boolean, found type: {type(component_wise)}.", ) self.ord = ord self.component_wise = component_wise super().__init__(univariate_scorer=(not component_wise), window=1) def __str__(self): return f"Norm (ord={self.ord})" def _score_core_from_prediction( self, actual_series: TimeSeries, pred_series: TimeSeries, ) -> TimeSeries: self._assert_deterministic(actual_series, "actual_series") self._assert_deterministic(pred_series, "pred_series") diff = actual_series - pred_series if self.component_wise: return diff.map(lambda x: np.abs(x)) else: diff_np = diff.all_values(copy=False) return TimeSeries.from_times_and_values( diff.time_index, np.linalg.norm(diff_np, ord=self.ord, axis=1) )