From 6d8b7c49746b0ac2e30ec502118ad78ff84744f9 Mon Sep 17 00:00:00 2001 From: LouisCarpentier42 Date: Thu, 23 Oct 2025 15:45:33 +0200 Subject: [PATCH 1/3] fix: LocalPolynomialApproximation Signed-off-by: LouisCarpentier42 --- docs/additional_information/changelog.rst | 3 ++ .../_LocalPolynomialApproximation.py | 40 ++++++++----------- 2 files changed, 20 insertions(+), 23 deletions(-) diff --git a/docs/additional_information/changelog.rst b/docs/additional_information/changelog.rst index dc75961..501240c 100644 --- a/docs/additional_information/changelog.rst +++ b/docs/additional_information/changelog.rst @@ -14,6 +14,9 @@ Changed Fixed ^^^^^ +- Fixed bug in ``LocalPolynomialApproximation`` when the variance of a neighborhood, + which would lead to nan values in the anomaly score if ``variance=True``. Simultaneously + integrated typing validation. [0.5.0] - 2025-10-06 ------ diff --git a/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py b/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py index 1ee2545..6bbea76 100644 --- a/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py +++ b/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py @@ -4,6 +4,7 @@ from dtaianomaly import utils from dtaianomaly.anomaly_detection._BaseDetector import BaseDetector, Supervision +from dtaianomaly.type_validation import BoolAttribute, IntegerAttribute __all__ = ["LocalPolynomialApproximation"] @@ -33,7 +34,8 @@ class LocalPolynomialApproximation(BaseDetector): and backward neighborhood, respectively. buffer : int, default=16 A buffer at the start and end of the time series, used to ensure that sufficient data is available - for fitting each polynomial. The buffer must be at least 3 to ensure that the . + for fitting each polynomial. The buffer must be at least 3 to ensure that there is at least a single + data point at the beginning and ending of the time series. Notes ----- @@ -52,11 +54,18 @@ class LocalPolynomialApproximation(BaseDetector): array([0., 0., 0., ..., 0., 0., 0.]...) """ - neighborhood: int | str + neighborhood: int power: int normalize_variance: bool buffer: int + attribute_validation = { + "neighborhood": IntegerAttribute(1), + "power": IntegerAttribute(1), + "normalize_variance": BoolAttribute(), + "buffer": IntegerAttribute(3), + } + def __init__( self, neighborhood: int, @@ -65,25 +74,6 @@ def __init__( buffer: int = 16, ): super().__init__(Supervision.UNSUPERVISED) - - if not isinstance(neighborhood, int) or isinstance(neighborhood, bool): - raise TypeError("`neighborhood` should be integer") - if neighborhood < 2: - raise ValueError("`neighborhood` should be at least 2") - - if not isinstance(power, int) or isinstance(power, bool): - raise TypeError("`power` should be integer") - if power < 1: - raise ValueError("`power` should be strictly positive") - - if not isinstance(normalize_variance, bool): - raise TypeError("'normalize_variance' should be a boolean") - - if not isinstance(buffer, int) or isinstance(buffer, bool): - raise TypeError("`buffer` should be integer") - if buffer < 3: - raise ValueError("`buffer` must be at least 3") - self.neighborhood = neighborhood self.power = power self.normalize_variance = normalize_variance @@ -173,8 +163,12 @@ def _local_poly_nb_parallel( # Normalize the variance, if requested if normalize_variance: - forward_score /= np.var(forward_neighborhood) ** 2 - backward_score /= np.var(backward_neighborhood) ** 2 + forward_var = np.var(forward_neighborhood) + if forward_var != 0: + forward_score /= forward_var**2 + backward_var = np.var(backward_neighborhood) + if backward_var != 0: + backward_score /= backward_var**2 decision_scores[t] = max(forward_score, backward_score) From 3517a9c000e5c8c8c6f17f16395da598dcfd2c3f Mon Sep 17 00:00:00 2001 From: LouisCarpentier42 Date: Thu, 23 Oct 2025 15:46:51 +0200 Subject: [PATCH 2/3] doc: Update changelog Signed-off-by: LouisCarpentier42 --- docs/additional_information/changelog.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/additional_information/changelog.rst b/docs/additional_information/changelog.rst index 501240c..d993162 100644 --- a/docs/additional_information/changelog.rst +++ b/docs/additional_information/changelog.rst @@ -15,8 +15,8 @@ Changed Fixed ^^^^^ - Fixed bug in ``LocalPolynomialApproximation`` when the variance of a neighborhood, - which would lead to nan values in the anomaly score if ``variance=True``. Simultaneously - integrated typing validation. + which would lead to nan values in the anomaly score if ``normalize_variance=True``. + Simultaneously integrated typing validation. [0.5.0] - 2025-10-06 ------ From 8fa79dca8639a3de9dc4833ba48963f14b13f5df Mon Sep 17 00:00:00 2001 From: LouisCarpentier42 Date: Thu, 23 Oct 2025 16:08:59 +0200 Subject: [PATCH 3/3] fix: Update boundary of neighborhood Signed-off-by: LouisCarpentier42 --- dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py b/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py index 6bbea76..7bda38b 100644 --- a/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py +++ b/dtaianomaly/anomaly_detection/_LocalPolynomialApproximation.py @@ -60,7 +60,7 @@ class LocalPolynomialApproximation(BaseDetector): buffer: int attribute_validation = { - "neighborhood": IntegerAttribute(1), + "neighborhood": IntegerAttribute(2), "power": IntegerAttribute(1), "normalize_variance": BoolAttribute(), "buffer": IntegerAttribute(3),