tsadmetrics 0.1.14__py3-none-any.whl → 0.1.16__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,8 +1,6 @@
1
1
  import numpy as np
2
2
  from .metric_utils import *
3
- from .metric_utils import get_events, calculate_intersection
4
-
5
-
3
+ from .validation import *
6
4
  from ._tsadeval.metrics import *
7
5
  from ._tsadeval.prts.basic_metrics_ts import ts_fscore
8
6
  from pate.PATE_metric import PATE
@@ -23,6 +21,8 @@ def point_wise_recall(y_true: np.array, y_pred: np.array):
23
21
  Returns:
24
22
  float: The point-wise recall score, which is the ratio of true positives to the sum of true positives and false negatives.
25
23
  """
24
+ validate_binary_inputs(y_true, y_pred)
25
+
26
26
  m = Pointwise_metrics(len(y_true),y_true,y_pred)
27
27
  m.set_confusion()
28
28
  TP,FN = m.tp,m.fn
@@ -47,6 +47,8 @@ def point_wise_precision(y_true: np.array, y_pred: np.array):
47
47
  Returns:
48
48
  float: The point-wise precision score, which is the ratio of true positives to the sum of true positives and false positives.
49
49
  """
50
+ validate_binary_inputs(y_true, y_pred)
51
+
50
52
  m = Pointwise_metrics(len(y_true),y_true,y_pred)
51
53
  m.set_confusion()
52
54
  TP,FP = m.tp,m.fp
@@ -74,6 +76,8 @@ def point_wise_f_score(y_true: np.array, y_pred: np.array, beta=1):
74
76
  Returns:
75
77
  float: The point-wise F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
76
78
  """
79
+ validate_binary_inputs(y_true, y_pred)
80
+
77
81
  precision = point_wise_precision(y_true, y_pred)
78
82
  recall = point_wise_recall(y_true, y_pred)
79
83
 
@@ -93,6 +97,9 @@ def point_adjusted_recall(y_true: np.array, y_pred: np.array):
93
97
 
94
98
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
95
99
 
100
+ For more information, see the original paper:
101
+ https://doi.org/10.1145/3178876.3185996
102
+
96
103
  Parameters:
97
104
  y_true (np.array):
98
105
  The ground truth binary labels for the time series data.
@@ -102,6 +109,8 @@ def point_adjusted_recall(y_true: np.array, y_pred: np.array):
102
109
  Returns:
103
110
  float: The point-adjusted recall score, which is the ratio of true positives to the sum of true positives and false negatives.
104
111
  """
112
+ validate_binary_inputs(y_true, y_pred)
113
+
105
114
  if np.sum(y_pred) == 0:
106
115
  return 0
107
116
  m = PointAdjust(len(y_true),y_true,y_pred)
@@ -121,6 +130,9 @@ def point_adjusted_precision(y_true: np.array, y_pred: np.array):
121
130
 
122
131
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
123
132
 
133
+ For more information, see the original paper:
134
+ https://doi.org/10.1145/3178876.3185996
135
+
124
136
  Parameters:
125
137
  y_true (np.array):
126
138
  The ground truth binary labels for the time series data.
@@ -130,6 +142,8 @@ def point_adjusted_precision(y_true: np.array, y_pred: np.array):
130
142
  Returns:
131
143
  float: The point-adjusted precision score, which is the ratio of true positives to the sum of true positives and false positives.
132
144
  """
145
+ validate_binary_inputs(y_true, y_pred)
146
+
133
147
  if np.sum(y_pred) == 0:
134
148
  return 0
135
149
  m = PointAdjust(len(y_true),y_true,y_pred)
@@ -146,8 +160,12 @@ def point_adjusted_f_score(y_true: np.array, y_pred: np.array, beta=1):
146
160
  if at least one point within that segment is predicted as anomalous, all points in the segment
147
161
  are marked as correctly detected. The adjusted predictions are then compared to the ground-truth
148
162
  labels using the standard point-wise F-Score formulation.
163
+
149
164
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
150
165
 
166
+ For more information, see the original paper:
167
+ https://doi.org/10.1145/3178876.3185996
168
+
151
169
  Parameters:
152
170
  y_true (np.array):
153
171
  The ground truth binary labels for the time series data.
@@ -160,6 +178,8 @@ def point_adjusted_f_score(y_true: np.array, y_pred: np.array, beta=1):
160
178
  Returns:
161
179
  float: The point-adjusted F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
162
180
  """
181
+ validate_binary_inputs(y_true, y_pred)
182
+
163
183
  precision = point_adjusted_precision(y_true, y_pred)
164
184
  recall = point_adjusted_recall(y_true, y_pred)
165
185
 
@@ -181,6 +201,9 @@ def delay_th_point_adjusted_recall(y_true: np.array, y_pred: np.array, k: int):
181
201
 
182
202
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
183
203
 
204
+ For more information, see the original paper:
205
+ https://doi.org/10.1145/3292500.3330680
206
+
184
207
  Parameters:
185
208
  y_true (np.array):
186
209
  The ground truth binary labels for the time series data.
@@ -193,6 +216,8 @@ def delay_th_point_adjusted_recall(y_true: np.array, y_pred: np.array, k: int):
193
216
  Returns:
194
217
  float: The delay thresholded point-adjusted recall score, which is the ratio of true positives to the sum of true positives and false negatives.
195
218
  """
219
+ validate_binary_inputs(y_true, y_pred)
220
+
196
221
  if np.sum(y_pred) == 0:
197
222
  return 0
198
223
  m = DelayThresholdedPointAdjust(len(y_true),y_true,y_pred,k=k)
@@ -212,6 +237,9 @@ def delay_th_point_adjusted_precision(y_true: np.array, y_pred: np.array, k: int
212
237
 
213
238
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
214
239
 
240
+ For more information, see the original paper:
241
+ https://doi.org/10.1145/3292500.3330680
242
+
215
243
  Parameters:
216
244
  y_true (np.array):
217
245
  The ground truth binary labels for the time series data.
@@ -224,6 +252,8 @@ def delay_th_point_adjusted_precision(y_true: np.array, y_pred: np.array, k: int
224
252
  Returns:
225
253
  float: The delay thresholded point-adjusted precision score, which is the ratio of true positives to the sum of true positives and false positives.
226
254
  """
255
+ validate_binary_inputs(y_true, y_pred)
256
+
227
257
  if np.sum(y_pred) == 0:
228
258
  return 0
229
259
  m = DelayThresholdedPointAdjust(len(y_true),y_true,y_pred,k=k)
@@ -243,6 +273,9 @@ def delay_th_point_adjusted_f_score(y_true: np.array, y_pred: np.array, k: int,
243
273
 
244
274
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
245
275
 
276
+ For more information, see the original paper:
277
+ https://doi.org/10.1145/3292500.3330680
278
+
246
279
  Parameters:
247
280
  y_true (np.array):
248
281
  The ground truth binary labels for the time series data.
@@ -257,6 +290,8 @@ def delay_th_point_adjusted_f_score(y_true: np.array, y_pred: np.array, k: int,
257
290
  Returns:
258
291
  float: The delay thresholded point-adjusted F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
259
292
  """
293
+ validate_binary_inputs(y_true, y_pred)
294
+
260
295
  precision = delay_th_point_adjusted_precision(y_true, y_pred, k)
261
296
  recall = delay_th_point_adjusted_recall(y_true, y_pred, k)
262
297
 
@@ -272,12 +307,14 @@ def point_adjusted_at_k_recall(y_true: np.array, y_pred: np.array, k: float):
272
307
  This metric is based on the standard recall score, but applies a temporal adjustment
273
308
  to the predictions before computing it. Specifically, for each ground-truth anomalous segment,
274
309
  if at least K% of the points within that segment are predicted as anomalous, all points in
275
- the segment are marked as correctly detected. Otherwise, the entire segment is treated as
276
- missed, even if some points were correctly predicted. The adjusted predictions are then used
310
+ the segment are marked as correctly detected. The adjusted predictions are then used
277
311
  to compute the standard point-wise recall.
278
312
 
279
313
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
280
314
 
315
+ For more information, see the original paper:
316
+ https://ojs.aaai.org/index.php/AAAI/article/view/20680
317
+
281
318
  Parameters:
282
319
  y_true (np.array):
283
320
  The ground truth binary labels for the time series data.
@@ -289,6 +326,8 @@ def point_adjusted_at_k_recall(y_true: np.array, y_pred: np.array, k: float):
289
326
  Returns:
290
327
  float: The point-adjusted recall score, which is the ratio of true positives to the sum of true positives and false negatives.
291
328
  """
329
+ validate_binary_inputs(y_true, y_pred)
330
+
292
331
  m = PointAdjustKPercent(len(y_true),y_true,y_pred,k=k)
293
332
  TP,FN = m.tp,m.fn
294
333
  if TP == 0:
@@ -301,10 +340,13 @@ def point_adjusted_at_k_precision(y_true: np.array, y_pred: np.array, k: float):
301
340
  This metric is based on the standard precision score, but applies a temporal adjustment
302
341
  to the predictions before computing it. Specifically, for each ground-truth anomalous segment,
303
342
  if at least K% of the points within that segment are predicted as anomalous, all points in
304
- the segment are marked as correctly detected. Otherwise, the entire segment is treated as
305
- missed, even if some points were correctly predicted. The adjusted predictions are then used
343
+ the segment are marked as correctly detected. The adjusted predictions are then used
306
344
  to compute the standard point-wise precision.
345
+
307
346
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
347
+
348
+ For more information, see the original paper:
349
+ https://ojs.aaai.org/index.php/AAAI/article/view/20680
308
350
 
309
351
  Parameters:
310
352
  y_true (np.array):
@@ -317,6 +359,8 @@ def point_adjusted_at_k_precision(y_true: np.array, y_pred: np.array, k: float):
317
359
  Returns:
318
360
  float: The point-adjusted precision score, which is the ratio of true positives to the sum of true positives and false positives.
319
361
  """
362
+ validate_binary_inputs(y_true, y_pred)
363
+
320
364
  m = PointAdjustKPercent(len(y_true),y_true,y_pred,k=k)
321
365
  TP,FP = m.tp,m.fp
322
366
  if TP == 0:
@@ -329,11 +373,13 @@ def point_adjusted_at_k_f_score(y_true: np.array, y_pred: np.array, k: float, be
329
373
  This metric is based on the standard F-Score, but applies a temporal adjustment
330
374
  to the predictions before computing it. Specifically, for each ground-truth anomalous segment,
331
375
  if at least K% of the points within that segment are predicted as anomalous, all points in
332
- the segment are marked as correctly detected. Otherwise, the entire segment is treated as
333
- missed, even if some points were correctly predicted. The adjusted predictions are then used
376
+ the segment are marked as correctly detected. The adjusted predictions are then used
334
377
  to compute the standard F-Score precision.
335
378
 
336
379
  Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
380
+
381
+ For more information, see the original paper:
382
+ https://ojs.aaai.org/index.php/AAAI/article/view/20680
337
383
 
338
384
  Parameters:
339
385
  y_true (np.array):
@@ -349,6 +395,8 @@ def point_adjusted_at_k_f_score(y_true: np.array, y_pred: np.array, k: float, be
349
395
  Returns:
350
396
  float: The point-adjusted F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
351
397
  """
398
+ validate_binary_inputs(y_true, y_pred)
399
+
352
400
  precision = point_adjusted_at_k_precision(y_true, y_pred, k)
353
401
  recall = point_adjusted_at_k_recall(y_true, y_pred, k)
354
402
 
@@ -372,6 +420,9 @@ def latency_sparsity_aw_recall(y_true: np.array, y_pred: np.array, ni: int):
372
420
 
373
421
  Implementation of https://dl.acm.org/doi/10.1145/3447548.3467174
374
422
 
423
+ For more information, see the original paper:
424
+ https://doi.org/10.1145/3447548.3467174
425
+
375
426
  Parameters:
376
427
  y_true (np.array):
377
428
  The ground truth binary labels for the time series data.
@@ -383,6 +434,8 @@ def latency_sparsity_aw_recall(y_true: np.array, y_pred: np.array, ni: int):
383
434
  Returns:
384
435
  float: The latency and sparsity aware recall score, which is the ratio of true positives to the sum of true positives and false negatives.
385
436
  """
437
+ validate_binary_inputs(y_true, y_pred)
438
+
386
439
  if np.sum(y_pred) == 0:
387
440
  return 0
388
441
  m = LatencySparsityAware(len(y_true),y_true,y_pred,tw=ni)
@@ -402,8 +455,12 @@ def latency_sparsity_aw_precision(y_true: np.array, y_pred: np.array, ni: int):
402
455
  scattered false positives, predictions are subsampled using a sparsity factor n, so that
403
456
  only one prediction is considered every n time steps. The adjusted predictions are then used
404
457
  to compute the standard point-wise precision.
458
+
405
459
  Implementation of https://dl.acm.org/doi/10.1145/3447548.3467174
406
460
 
461
+ For more information, see the original paper:
462
+ https://doi.org/10.1145/3447548.3467174
463
+
407
464
  Parameters:
408
465
  y_true (np.array):
409
466
  The ground truth binary labels for the time series data.
@@ -415,6 +472,8 @@ def latency_sparsity_aw_precision(y_true: np.array, y_pred: np.array, ni: int):
415
472
  Returns:
416
473
  float: The latency and sparsity aware precision score, which is the ratio of true positives to the sum of true positives and false positives.
417
474
  """
475
+ validate_binary_inputs(y_true, y_pred)
476
+
418
477
  if np.sum(y_pred) == 0:
419
478
  return 0
420
479
  m = LatencySparsityAware(len(y_true),y_true,y_pred,tw=ni)
@@ -437,6 +496,9 @@ def latency_sparsity_aw_f_score(y_true: np.array, y_pred: np.array, ni: int, bet
437
496
 
438
497
  Implementation of https://dl.acm.org/doi/10.1145/3447548.3467174
439
498
 
499
+ For more information, see the original paper:
500
+ https://doi.org/10.1145/3447548.3467174
501
+
440
502
  Parameters:
441
503
  y_true (np.array):
442
504
  The ground truth binary labels for the time series data.
@@ -451,6 +513,8 @@ def latency_sparsity_aw_f_score(y_true: np.array, y_pred: np.array, ni: int, bet
451
513
  Returns:
452
514
  float: The latency and sparsity aware F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
453
515
  """
516
+ validate_binary_inputs(y_true, y_pred)
517
+
454
518
  if np.sum(y_pred) == 0:
455
519
  return 0
456
520
 
@@ -472,7 +536,10 @@ def segment_wise_recall(y_true: np.array, y_pred: np.array):
472
536
  overlap with any ground-truth anomaly. The final recall is computed using these adjusted
473
537
  segment-level counts.
474
538
 
475
- Implementation of https://arxiv.org/pdf/1802.04431
539
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
540
+
541
+ For more information, see the original paper:
542
+ https://doi.org/10.1145/3219819.3219845
476
543
 
477
544
  Parameters:
478
545
  y_true (np.array):
@@ -483,6 +550,8 @@ def segment_wise_recall(y_true: np.array, y_pred: np.array):
483
550
  Returns:
484
551
  float: The segment-wise recall score, which is the ratio of true positives to the sum of true positives and false negatives.
485
552
  """
553
+ validate_binary_inputs(y_true, y_pred)
554
+
486
555
  m = Segmentwise_metrics(len(y_true),y_true,y_pred)
487
556
  TP,FN = m.tp,m.fn
488
557
  if TP == 0:
@@ -500,7 +569,10 @@ def segment_wise_precision(y_true: np.array, y_pred: np.array):
500
569
  overlap with any ground-truth anomaly. The final precision is computed using these adjusted
501
570
  segment-level counts.
502
571
 
503
- Implementation of https://arxiv.org/pdf/1802.04431
572
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
573
+
574
+ For more information, see the original paper:
575
+ https://doi.org/10.1145/3219819.3219845
504
576
 
505
577
  Parameters:
506
578
  y_true (np.array):
@@ -511,6 +583,8 @@ def segment_wise_precision(y_true: np.array, y_pred: np.array):
511
583
  Returns:
512
584
  float: The segment-wise precision score, which is the ratio of true positives to the sum of true positives and false positives.
513
585
  """
586
+ validate_binary_inputs(y_true, y_pred)
587
+
514
588
  m = Segmentwise_metrics(len(y_true),y_true,y_pred)
515
589
  TP,FP = m.tp,m.fp
516
590
  if TP == 0:
@@ -528,7 +602,10 @@ def segment_wise_f_score(y_true: np.array, y_pred: np.array, beta=1):
528
602
  overlap with any ground-truth anomaly. The final F-score is computed using these adjusted
529
603
  segment-level counts.
530
604
 
531
- Implementation of https://arxiv.org/pdf/1802.04431
605
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
606
+
607
+ For more information, see the original paper:
608
+ https://doi.org/10.1145/3219819.3219845
532
609
 
533
610
  Parameters:
534
611
  y_true (np.array):
@@ -543,6 +620,8 @@ def segment_wise_f_score(y_true: np.array, y_pred: np.array, beta=1):
543
620
  float: The segment-wise F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
544
621
 
545
622
  """
623
+ validate_binary_inputs(y_true, y_pred)
624
+
546
625
  m = Segmentwise_metrics(len(y_true),y_true,y_pred)
547
626
  TP,FN,FP = m.tp,m.fn,m.fp
548
627
  if TP==0:
@@ -565,6 +644,9 @@ def composite_f_score(y_true: np.array, y_pred: np.array, beta=1):
565
644
 
566
645
  Implementation of https://ieeexplore.ieee.org/document/9525836
567
646
 
647
+ For more information, see the original paper:
648
+ https://doi.org/10.1109/TNNLS.2021.3105827
649
+
568
650
  Parameters:
569
651
  y_true (np.array):
570
652
  The ground truth binary labels for the time series data.
@@ -578,6 +660,8 @@ def composite_f_score(y_true: np.array, y_pred: np.array, beta=1):
578
660
  float: The composite F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
579
661
 
580
662
  """
663
+ validate_binary_inputs(y_true, y_pred)
664
+
581
665
  m = Composite_f(len(y_true),y_true,y_pred)
582
666
  #Point wise precision
583
667
  precision = m.precision()
@@ -595,11 +679,14 @@ def time_tolerant_recall(y_true: np.array, y_pred: np.array, t: int) -> float:
595
679
  Calculate time tolerant recall for anomaly detection in time series.
596
680
  This metric is based on the standard recall, but applies a temporal adjustment
597
681
  to the predictions before computing it. Specifically, a predicted anomalous point is considered
598
- a true positive if it lies within a temporal window of size τ around any ground-truth anomalous point.
682
+ a true positive if it lies within a temporal window of size :math:`{\\tau}` around any ground-truth anomalous point.
599
683
  This allows for small temporal deviations in the predictions to be tolerated. The adjusted predictions are then used
600
684
  to compute the standard point-wise recall.
601
685
 
602
- Implementation of https://arxiv.org/pdf/1802.04431
686
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
687
+
688
+ For more information, see the original paper:
689
+ 10.48550/arXiv.2008.05788
603
690
 
604
691
  Parameters:
605
692
  y_true (np.array):
@@ -612,6 +699,8 @@ def time_tolerant_recall(y_true: np.array, y_pred: np.array, t: int) -> float:
612
699
  Returns:
613
700
  float: The time tolerant recall score, which is the ratio of true positives to the sum of true positives and false negatives.
614
701
  """
702
+ validate_binary_inputs(y_true, y_pred)
703
+
615
704
  if np.sum(y_pred) == 0:
616
705
  return 0
617
706
 
@@ -623,11 +712,14 @@ def time_tolerant_precision(y_true: np.array, y_pred: np.array, t: int) -> float
623
712
  Calculate time tolerant precision for anomaly detection in time series.
624
713
  This metric is based on the standard precision, but applies a temporal adjustment
625
714
  to the predictions before computing it. Specifically, a predicted anomalous point is considered
626
- a true positive if it lies within a temporal window of size τ around any ground-truth anomalous point.
715
+ a true positive if it lies within a temporal window of size :math:`{\\tau}` around any ground-truth anomalous point.
627
716
  This allows for small temporal deviations in the predictions to be tolerated. The adjusted predictions are then used
628
717
  to compute the standard point-wise precision.
629
718
 
630
- Implementation of https://arxiv.org/pdf/1802.04431
719
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
720
+
721
+ For more information, see the original paper:
722
+ 10.48550/arXiv.2008.05788
631
723
 
632
724
  Parameters:
633
725
  y_true (np.array):
@@ -640,6 +732,8 @@ def time_tolerant_precision(y_true: np.array, y_pred: np.array, t: int) -> float
640
732
  Returns:
641
733
  float: The time tolerant precision score, which is the ratio of true positives to the sum of true positives and false positives.
642
734
  """
735
+ validate_binary_inputs(y_true, y_pred)
736
+
643
737
  if np.sum(y_pred) == 0:
644
738
  return 0
645
739
  m = Time_Tolerant(len(y_true),y_true,y_pred, d=t)
@@ -651,11 +745,14 @@ def time_tolerant_f_score(y_true: np.array, y_pred: np.array, t: int, beta=1):
651
745
  Calculate time tolerant F-score for anomaly detection in time series.
652
746
  This metric is based on the standard F-score, but applies a temporal adjustment
653
747
  to the predictions before computing it. Specifically, a predicted anomalous point is considered
654
- a true positive if it lies within a temporal window of size τ around any ground-truth anomalous point.
748
+ a true positive if it lies within a temporal window of size :math:`{\\tau}` around any ground-truth anomalous point.
655
749
  This allows for small temporal deviations in the predictions to be tolerated.The adjusted predictions are then used
656
750
  to compute the standard point-wise F-Score.
657
751
 
658
- Implementation of https://arxiv.org/pdf/1802.04431
752
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
753
+
754
+ For more information, see the original paper:
755
+ 10.48550/arXiv.2008.05788
659
756
 
660
757
  Parameters:
661
758
  y_true (np.array):
@@ -672,6 +769,8 @@ def time_tolerant_f_score(y_true: np.array, y_pred: np.array, t: int, beta=1):
672
769
  float: The time tolerant F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
673
770
 
674
771
  """
772
+ validate_binary_inputs(y_true, y_pred)
773
+
675
774
  precision = time_tolerant_precision(y_true,y_pred,t)
676
775
  recall = time_tolerant_recall(y_true,y_pred,t)
677
776
  if precision==0 or recall==0:
@@ -687,9 +786,11 @@ def range_based_recall(y_true: np.array, y_pred: np.array, alpha: float, bias='f
687
786
  rather than individual points. For each true anomaly range, it computes a score that rewards
688
787
  (1) detecting the existence of the range, (2) the proportion of overlap, and (3) penalties or
689
788
  bonuses based on the position and fragmentation of predicted segments. These components are
690
- weighted by α (existence vs. overlap) and further shaped by customizable bias functions
789
+ weighted by :math:`{\\alpha}` (existence vs. overlap) and further shaped by customizable bias functions
691
790
  for positional and cardinality factors.
692
791
 
792
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
793
+
693
794
  For more information, see the original paper:
694
795
  https://proceedings.neurips.cc/paper_files/paper/2018/file/8f468c873a32bb0619eaeb2050ba45d1-Paper.pdf
695
796
 
@@ -699,7 +800,7 @@ def range_based_recall(y_true: np.array, y_pred: np.array, alpha: float, bias='f
699
800
  y_pred (np.array):
700
801
  The predicted binary labels for the time series data.
701
802
  alpha (float):
702
- Relative importance of existence reward. 0 alpha 1.
803
+ Relative importance of existence reward. 0 \\leq alpha \\leq 1.
703
804
  bias (str):
704
805
  Positional bias. This should be "flat", "front", "middle", or "back".
705
806
  cardinality_mode (str, optional):
@@ -708,6 +809,8 @@ def range_based_recall(y_true: np.array, y_pred: np.array, alpha: float, bias='f
708
809
  Returns:
709
810
  float: The range-based recall score.
710
811
  """
812
+ validate_binary_inputs(y_true, y_pred)
813
+
711
814
  if np.sum(y_pred) == 0:
712
815
  return 0
713
816
  m = Range_PR(len(y_true),y_true,y_pred,cardinality=cardinality_mode, alpha=alpha,bias=bias)
@@ -723,7 +826,11 @@ def range_based_precision(y_true: np.array, y_pred: np.array, alpha: float, bias
723
826
  predicted anomaly range is evaluated for (1) overlap with any true ranges, (2) the size of
724
827
  that overlap, and (3) positional and fragmentation effects via bias functions. Cardinality
725
828
  penalties can be applied when a single true range is covered by multiple predicted ranges.
829
+ These components are weighted by :math:`{\\alpha}` (existence vs. overlap) and further shaped by customizable bias functions
830
+ for positional and cardinality factors.
726
831
 
832
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
833
+
727
834
  For more information, see the original paper:
728
835
  https://proceedings.neurips.cc/paper_files/paper/2018/file/8f468c873a32bb0619eaeb2050ba45d1-Paper.pdf
729
836
 
@@ -733,7 +840,7 @@ def range_based_precision(y_true: np.array, y_pred: np.array, alpha: float, bias
733
840
  y_pred (np.array):
734
841
  The predicted binary labels for the time series data.
735
842
  alpha (float):
736
- Relative importance of existence reward. 0 alpha 1.
843
+ Relative importance of existence reward. 0 \\leq alpha \\leq 1.
737
844
  bias (str):
738
845
  Positional bias. This should be "flat", "front", "middle", or "back".
739
846
  cardinality_mode (str, optional):
@@ -742,6 +849,8 @@ def range_based_precision(y_true: np.array, y_pred: np.array, alpha: float, bias
742
849
  Returns:
743
850
  float: The range-based precision score.
744
851
  """
852
+ validate_binary_inputs(y_true, y_pred)
853
+
745
854
  if np.sum(y_pred) == 0:
746
855
  return 0
747
856
  m = Range_PR(len(y_true),y_true,y_pred,cardinality=cardinality_mode, alpha=alpha,bias=bias)
@@ -761,6 +870,8 @@ def range_based_f_score(y_true: np.array, y_pred: np.array, p_alpha: float, r_al
761
870
  weighting, positional bias, and cardinality factors—allowing fine-grained control over how
762
871
  both missed detections and false alarms are penalized in a temporal context.
763
872
 
873
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
874
+
764
875
  For more information, see the original paper:
765
876
  https://proceedings.neurips.cc/paper_files/paper/2018/file/8f468c873a32bb0619eaeb2050ba45d1-Paper.pdf
766
877
 
@@ -770,8 +881,10 @@ def range_based_f_score(y_true: np.array, y_pred: np.array, p_alpha: float, r_al
770
881
  The ground truth binary labels for the time series data.
771
882
  y_pred (np.array):
772
883
  The predicted binary labels for the time series data.
773
- alpha (float):
774
- Relative importance of existence reward. 0 alpha 1.
884
+ p_alpha (float):
885
+ Relative importance of existence reward for precision. 0 \\leq alpha \\leq 1.
886
+ r_alpha (float):
887
+ Relative importance of existence reward for recall. 0 \\leq alpha \\leq 1.
775
888
  p_bias (str):
776
889
  Positional bias for precision. This should be "flat", "front", "middle", or "back".
777
890
  r_bias (str):
@@ -785,6 +898,8 @@ def range_based_f_score(y_true: np.array, y_pred: np.array, p_alpha: float, r_al
785
898
  Returns:
786
899
  float: The range-based F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
787
900
  """
901
+ validate_binary_inputs(y_true, y_pred)
902
+
788
903
  if np.sum(y_pred) == 0:
789
904
  return 0
790
905
  f = ts_fscore(y_true, y_pred, beta=beta, p_alpha=p_alpha, r_alpha=r_alpha, cardinality=cardinality_mode, p_bias=p_bias, r_bias=r_bias)
@@ -799,35 +914,42 @@ def ts_aware_recall(y_true: np.array, y_pred: np.array, alpha: float, delta: flo
799
914
 
800
915
  This metric is based on the range_based_recall, but introduces two key modifications.
801
916
  First, a predicted anomalous segment is only counted as a true positive if it covers at least a fraction
802
- θ of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
803
- length δ at its end, within which any overlap contribution decays linearly from full weight down to zero.
917
+ :math:`{\\theta}` of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
918
+ length :math:`{\\delta}` at its end, within which any overlap contribution decays linearly from full weight down to zero.
804
919
  Unlike the original range-based formulation, this variant omits cardinality and positional bias terms,
805
920
  focusing solely on overlap fraction and end‑tolerance decay.
806
921
 
922
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
923
+
924
+ For more information, see the original paper:
925
+ https://doi.org/10.1145/3357384.3358118
926
+
807
927
  Parameters:
808
928
  y_true (np.array):
809
929
  The ground truth binary labels for the time series data.
810
930
  y_pred (np.array):
811
931
  The predicted binary labels for the time series data.
812
932
  alpha (float):
813
- Relative importance of the existence reward versus overlap reward (0 α 1).
933
+ Relative importance of the existence reward versus overlap reward (0 \\leq :math:`{\\alpha}` \\leq 1).
814
934
  delta (float):
815
935
  Tolerance window length at the end of each true anomaly segment.
816
- - If past_range is True, δ must be a float in (0, 1], representing the fraction of the segment’s
817
- length to extend. E.g., δ = 0.5 extends a segment of length 10 by 5 time steps.
818
- - If past_range is False, δ must be a non-negative integer, representing an absolute number of
936
+ - If past_range is True, :math:`{\\delta}` must be a float in (0, 1], representing the fraction of the segment’s
937
+ length to extend. E.g., :math:`{\\delta}` = 0.5 extends a segment of length 10 by 5 time steps.
938
+ - If past_range is False, :math:`{\\delta}` must be a non-negative integer, representing an absolute number of
819
939
  time steps to extend each segment.
820
940
  theta (float):
821
- Minimum fraction (0 θ 1) of the true anomaly range that must be overlapped by
941
+ Minimum fraction (0 \\leq :math:`{\\theta}` \\leq 1) of the true anomaly range that must be overlapped by
822
942
  predictions for the segment to count as detected.
823
943
  past_range (bool):
824
- Determines how δ is interpreted.
825
- - True: δ is treated as a fractional extension of each segment’s length.
826
- - False: δ is treated as an absolute number of time steps.
944
+ Determines how :math:`{\\delta}` is interpreted.
945
+ - True: :math:`{\\delta}` is treated as a fractional extension of each segment’s length.
946
+ - False: :math:`{\\delta}` is treated as an absolute number of time steps.
827
947
 
828
948
  Returns:
829
949
  float: The time series aware recall score.
830
950
  """
951
+ validate_binary_inputs(y_true, y_pred)
952
+
831
953
  m = TaF(len(y_true),y_true,y_pred,alpha=alpha,theta=theta,delta=delta,past_range=past_range)
832
954
  return m.recall()
833
955
 
@@ -840,35 +962,42 @@ def ts_aware_precision(y_true: np.array, y_pred: np.array,alpha: float, delta: f
840
962
 
841
963
  This metric is based on the range_based_precision, but introduces two key modifications.
842
964
  First, a predicted anomalous segment is only counted as a true positive if it covers at least a fraction
843
- θ of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
844
- length δ at its end, within which any overlap contribution decays linearly from full weight down to zero.
965
+ :math:`{\\theta}` of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
966
+ length :math:`{\\delta}` at its end, within which any overlap contribution decays linearly from full weight down to zero.
845
967
  Unlike the original range-based formulation, this variant omits cardinality and positional bias terms,
846
968
  focusing solely on overlap fraction and end‑tolerance decay.
847
969
 
970
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
971
+
972
+ For more information, see the original paper:
973
+ https://doi.org/10.1145/3357384.3358118
974
+
848
975
  Parameters:
849
976
  y_true (np.array):
850
977
  The ground truth binary labels for the time series data.
851
978
  y_pred (np.array):
852
979
  The predicted binary labels for the time series data.
853
980
  alpha (float):
854
- Relative importance of the existence reward versus overlap reward (0 α 1).
981
+ Relative importance of the existence reward versus overlap reward (0 \\leq :math:`{\\alpha}` \\leq 1).
855
982
  delta (float):
856
983
  Tolerance window length at the end of each true anomaly segment.
857
- - If past_range is True, δ must be a float in (0, 1], representing the fraction of the segment’s
858
- length to extend. E.g., δ = 0.5 extends a segment of length 10 by 5 time steps.
859
- - If past_range is False, δ must be a non-negative integer, representing an absolute number of
984
+ - If past_range is True, :math:`{\\delta}` must be a float in (0, 1], representing the fraction of the segment’s
985
+ length to extend. E.g., :math:`{\\delta}` = 0.5 extends a segment of length 10 by 5 time steps.
986
+ - If past_range is False, :math:`{\\delta}` must be a non-negative integer, representing an absolute number of
860
987
  time steps to extend each segment.
861
988
  theta (float):
862
- Minimum fraction (0 θ 1) of the true anomaly range that must be overlapped by
989
+ Minimum fraction (0 \\leq :math:`{\\theta}` \\leq 1) of the true anomaly range that must be overlapped by
863
990
  predictions for the segment to count as detected.
864
991
  past_range (bool):
865
- Determines how δ is interpreted.
866
- - True: δ is treated as a fractional extension of each segment’s length.
867
- - False: δ is treated as an absolute number of time steps.
992
+ Determines how :math:`{\\delta}` is interpreted.
993
+ - True: :math:`{\\delta}` is treated as a fractional extension of each segment’s length.
994
+ - False: :math:`{\\delta}` is treated as an absolute number of time steps.
868
995
 
869
996
  Returns:
870
997
  float: The time series aware precision score.
871
998
  """
999
+ validate_binary_inputs(y_true, y_pred)
1000
+
872
1001
  m = TaF(len(y_true),y_true,y_pred,alpha=alpha,theta=theta,delta=delta,past_range=past_range)
873
1002
  return m.precision()
874
1003
 
@@ -882,36 +1011,45 @@ def ts_aware_f_score(y_true: np.array, y_pred: np.array, beta: float, alpha: flo
882
1011
 
883
1012
  This metric is based on the range_based_f_score, but introduces two key modifications.
884
1013
  First, a predicted anomalous segment is only counted as a true positive if it covers at least a fraction
885
- θ of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
886
- length δ at its end, within which any overlap contribution decays linearly from full weight down to zero.
1014
+ :math:`{\\theta}` of the ground‑truth anomaly range. Second, each labeled anomaly is extended by a tolerance window of
1015
+ length :math:`{\\delta}` at its end, within which any overlap contribution decays linearly from full weight down to zero.
887
1016
  Unlike the original range-based formulation, this variant omits cardinality and positional bias terms,
888
1017
  focusing solely on overlap fraction and end‑tolerance decay.
889
1018
 
1019
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1020
+
1021
+ For more information, see the original paper:
1022
+ https://doi.org/10.1145/3357384.3358118
1023
+
890
1024
  Parameters:
891
1025
  y_true (np.array):
892
1026
  The ground truth binary labels for the time series data.
893
1027
  y_pred (np.array):
894
1028
  The predicted binary labels for the time series data.
1029
+ beta (float):
1030
+ The beta value, which determines the weight of precision in the combined score.
1031
+ Default is 1, which gives equal weight to precision and recall.
895
1032
  alpha (float):
896
- Relative importance of the existence reward versus overlap reward (0 α 1).
1033
+ Relative importance of the existence reward versus overlap reward (0 \\leq :math:`{\\alpha}` \\leq 1).
897
1034
  delta (float):
898
1035
  Tolerance window length at the end of each true anomaly segment.
899
- - If past_range is True, δ must be a float in (0, 1], representing the fraction of the segment’s
900
- length to extend. E.g., δ = 0.5 extends a segment of length 10 by 5 time steps.
901
- - If past_range is False, δ must be a non-negative integer, representing an absolute number of
1036
+ - If past_range is True, :math:`{\\delta}` must be a float in (0, 1], representing the fraction of the segment’s
1037
+ length to extend. E.g., :math:`{\\delta}` = 0.5 extends a segment of length 10 by 5 time steps.
1038
+ - If past_range is False, :math:`{\\delta}` must be a non-negative integer, representing an absolute number of
902
1039
  time steps to extend each segment.
903
1040
  theta (float):
904
- Minimum fraction (0 θ 1) of the true anomaly range that must be overlapped by
1041
+ Minimum fraction (0 \\leq :math:`{\\theta}` \\leq 1) of the true anomaly range that must be overlapped by
905
1042
  predictions for the segment to count as detected.
906
1043
  past_range (bool):
907
- Determines how δ is interpreted.
908
- - True: δ is treated as a fractional extension of each segment’s length.
909
- - False: δ is treated as an absolute number of time steps.
1044
+ Determines how :math:`{\\delta}` is interpreted.
1045
+ - True: :math:`{\\delta}` is treated as a fractional extension of each segment’s length.
1046
+ - False: :math:`{\\delta}` is treated as an absolute number of time steps.
910
1047
 
911
1048
  Returns:
912
1049
  float: The time series aware F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
913
1050
  """
914
-
1051
+ validate_binary_inputs(y_true, y_pred)
1052
+
915
1053
  m = TaF(len(y_true),y_true,y_pred,alpha=alpha,theta=theta,delta=delta,past_range=past_range)
916
1054
  precision = m.precision()
917
1055
  recall = m.recall()
@@ -929,10 +1067,13 @@ def enhanced_ts_aware_recall(y_true: np.array, y_pred: np.array, theta: float):
929
1067
  Calculate enhanced time series aware recall for anomaly detection in time series.
930
1068
 
931
1069
  This metric is similar to the range-based recall in that it accounts for both detection existence
932
- and overlap proportion. Additionally, it requires that a significant fraction θ of each true anomaly
933
- segment be detected, and that a significant fraction γ of each predicted segment overlaps with the
934
- ground truth. Finally, recall contributions from each event are weighted by the square root of the
935
- true segment’s length, providing a compromise between point-wise and segment-wise approaches.
1070
+ and overlap proportion. Additionally, it requires that a significant fraction :math:`{\\theta}` of each true anomaly
1071
+ segment be detected.
1072
+
1073
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1074
+
1075
+ For more information, see the original paper:
1076
+ https://doi.org/10.1145/3477314.3507024
936
1077
 
937
1078
  Parameters:
938
1079
  y_true (np.array):
@@ -940,12 +1081,14 @@ def enhanced_ts_aware_recall(y_true: np.array, y_pred: np.array, theta: float):
940
1081
  y_pred (np.array):
941
1082
  The predicted binary labels for the time series data.
942
1083
  theta (float):
943
- Minimum fraction (0 θ 1) of a true segment that must be overlapped
1084
+ Minimum fraction (0 \\leq :math:`{\\theta}` \\leq 1) of a true segment that must be overlapped
944
1085
  by predictions to count as detected.
945
1086
 
946
1087
  Returns:
947
1088
  float: The time series aware recall score.
948
1089
  """
1090
+ validate_binary_inputs(y_true, y_pred)
1091
+
949
1092
  if np.sum(y_pred) == 0:
950
1093
  return 0
951
1094
  m = eTaF(len(y_true),y_true,y_pred,theta_p=theta)
@@ -958,11 +1101,14 @@ def enhanced_ts_aware_precision(y_true: np.array, y_pred: np.array, theta: float
958
1101
  """
959
1102
  Calculate enhanced time series aware precision for anomaly detection in time series.
960
1103
 
961
- This metric is similar to the range-based precision in that it accounts for both detection existence
962
- and overlap proportion. Additionally, it requires that a significant fraction θ of each true anomaly
963
- segment be detected, and that a significant fraction γ of each predicted segment overlaps with the
964
- ground truth. Finally, precision contributions from each event are weighted by the square root of the
965
- true segment’s length, providing a compromise between point-wise and segment-wise approaches.
1104
+ This metric is similar to the range-based precision. Additionally, it requires that a significant fraction :math:`{\\theta}`
1105
+ of each predicted segment overlaps with the ground truth. Finally, precision contributions from each event are weighted by
1106
+ the square root of the true segment’s length, providing a compromise between point-wise and segment-wise approaches.
1107
+
1108
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1109
+
1110
+ For more information, see the original paper:
1111
+ https://doi.org/10.1145/3477314.3507024
966
1112
 
967
1113
  Parameters:
968
1114
  y_true (np.array):
@@ -970,12 +1116,14 @@ def enhanced_ts_aware_precision(y_true: np.array, y_pred: np.array, theta: float
970
1116
  y_pred (np.array):
971
1117
  The predicted binary labels for the time series data.
972
1118
  theta (float):
973
- Minimum fraction (0 θ 1) of a true segment that must be overlapped
974
- by predictions to count as detected.
1119
+ Minimum fraction (0 \\leq :math:`{\\theta}` \\leq 1) of a predicted segment that must be overlapped
1120
+ by ground truth to count as detected.
975
1121
 
976
1122
  Returns:
977
1123
  float: The time series aware precision score.
978
1124
  """
1125
+ validate_binary_inputs(y_true, y_pred)
1126
+
979
1127
  if np.sum(y_pred) == 0:
980
1128
  return 0
981
1129
  m = eTaF(len(y_true),y_true,y_pred,theta_p=theta)
@@ -990,23 +1138,33 @@ def enhanced_ts_aware_f_score(y_true: np.array, y_pred: np.array, theta_p: float
990
1138
  Calculate enhanced time series aware F-score for anomaly detection in time series.
991
1139
 
992
1140
  This metric is similar to the range-based F-score in that it accounts for both detection existence
993
- and overlap proportion. Additionally, it requires that a significant fraction θ of each true anomaly
994
- segment be detected, and that a significant fraction γ of each predicted segment overlaps with the
1141
+ and overlap proportion. Additionally, it requires that a significant fraction :math:`{\\theta_r}` of each true anomaly
1142
+ segment be detected, and that a significant fraction :math:`{\\theta_p}` of each predicted segment overlaps with the
995
1143
  ground truth. Finally, F-score contributions from each event are weighted by the square root of the
996
1144
  true segment’s length, providing a compromise between point-wise and segment-wise approaches.
997
1145
 
1146
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1147
+
1148
+ For more information, see the original paper:
1149
+ https://doi.org/10.1145/3477314.3507024
1150
+
998
1151
  Parameters:
999
1152
  y_true (np.array):
1000
1153
  The ground truth binary labels for the time series data.
1001
1154
  y_pred (np.array):
1002
1155
  The predicted binary labels for the time series data.
1003
- theta (float):
1004
- Minimum fraction (0 θ 1) of a true segment that must be overlapped
1156
+ theta_p (float):
1157
+ Minimum fraction (0 \\leq :math:`{\\theta_p}` \\leq 1) of a predicted segment that must be overlapped
1158
+ by ground truth to count as detected.
1159
+ theta_r (float):
1160
+ Minimum fraction (0 \\leq :math:`{\\theta_r}` \\leq 1) of a true segment that must be overlapped
1005
1161
  by predictions to count as detected.
1006
1162
 
1007
1163
  Returns:
1008
1164
  float: The time series aware F-score, which is the harmonic mean of precision and recall, adjusted by the beta value.
1009
1165
  """
1166
+ validate_binary_inputs(y_true, y_pred)
1167
+
1010
1168
  if np.sum(y_pred) == 0:
1011
1169
  return 0
1012
1170
  m = eTaF(len(y_true),y_true,y_pred,theta_p=theta_p, theta_r=theta_r)
@@ -1022,6 +1180,11 @@ def affiliation_based_recall(y_true: np.array, y_pred: np.array):
1022
1180
  It computes the average distance from each ground truth anomaly point to the nearest
1023
1181
  predicted anomaly point.
1024
1182
 
1183
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1184
+
1185
+ For more information, see the original paper:
1186
+ https://dl.acm.org/doi/10.1145/3534678.3539339
1187
+
1025
1188
  Parameters:
1026
1189
  y_true (np.array):
1027
1190
  The ground truth binary labels for the time series data.
@@ -1031,6 +1194,8 @@ def affiliation_based_recall(y_true: np.array, y_pred: np.array):
1031
1194
  Returns:
1032
1195
  float: The affiliation based recall score.
1033
1196
  """
1197
+ validate_binary_inputs(y_true, y_pred)
1198
+
1034
1199
  if np.sum(y_pred) == 0:
1035
1200
  return 0
1036
1201
  m = Affiliation(len(y_true),y_true,y_pred)
@@ -1046,6 +1211,11 @@ def affiliation_based_precision(y_true: np.array, y_pred: np.array):
1046
1211
  It computes the average distance from each predicted anomaly point to the nearest
1047
1212
  ground truth anomaly point.
1048
1213
 
1214
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1215
+
1216
+ For more information, see the original paper:
1217
+ https://dl.acm.org/doi/10.1145/3534678.3539339
1218
+
1049
1219
  Parameters:
1050
1220
  y_true (np.array):
1051
1221
  The ground truth binary labels for the time series data.
@@ -1056,6 +1226,8 @@ def affiliation_based_precision(y_true: np.array, y_pred: np.array):
1056
1226
  Returns:
1057
1227
  float: The affiliation based precision score.
1058
1228
  """
1229
+ validate_binary_inputs(y_true, y_pred)
1230
+
1059
1231
  if np.sum(y_pred) == 0:
1060
1232
  return 0
1061
1233
  m = Affiliation(len(y_true),y_true,y_pred)
@@ -1068,11 +1240,16 @@ def affiliation_based_f_score(y_true: np.array, y_pred: np.array, beta=1):
1068
1240
  Calculate affiliation based F-score for anomaly detection in time series.
1069
1241
 
1070
1242
  This metric combines the affiliation-based precision and recall into a single score
1071
- using the harmonic mean, adjusted by a weight β to control the relative importance
1243
+ using the harmonic mean, adjusted by a weight :math:`{\\beta}` to control the relative importance
1072
1244
  of recall versus precision. Since both precision and recall are distance-based,
1073
1245
  the F-score reflects a balance between how well predicted anomalies align with true
1074
1246
  anomalies and vice versa.
1075
1247
 
1248
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1249
+
1250
+ For more information, see the original paper:
1251
+ https://dl.acm.org/doi/10.1145/3534678.3539339
1252
+
1076
1253
  Parameters:
1077
1254
  y_true (np.array):
1078
1255
  The ground truth binary labels for the time series data.
@@ -1085,6 +1262,8 @@ def affiliation_based_f_score(y_true: np.array, y_pred: np.array, beta=1):
1085
1262
  Returns:
1086
1263
  float: The affiliation based F-score.
1087
1264
  """
1265
+ validate_binary_inputs(y_true, y_pred)
1266
+
1088
1267
  if np.sum(y_pred) == 0:
1089
1268
  return 0
1090
1269
  m = Affiliation(len(y_true),y_true,y_pred)
@@ -1100,6 +1279,11 @@ def nab_score(y_true: np.array, y_pred: np.array):
1100
1279
  positively to the score, with earlier detections receiving higher rewards. In contrast, every false
1101
1280
  positive prediction contributes negatively.
1102
1281
 
1282
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1283
+
1284
+ For more information, see the original paper:
1285
+ https://doi.org/10.1109/ICMLA.2015.141
1286
+
1103
1287
  Parameters:
1104
1288
  y_true (np.array):
1105
1289
  The ground truth binary labels for the time series data.
@@ -1110,7 +1294,8 @@ def nab_score(y_true: np.array, y_pred: np.array):
1110
1294
  Returns:
1111
1295
  float: The nab score.
1112
1296
  """
1113
-
1297
+ validate_binary_inputs(y_true, y_pred)
1298
+
1114
1299
  m = NAB_score(len(y_true),y_true,y_pred)
1115
1300
  return m.get_score()
1116
1301
 
@@ -1122,6 +1307,10 @@ def temporal_distance(y_true: np.array, y_pred: np.array, distance: int = 0):
1122
1307
  the closest predicted anomaly point, and from each predicted anomaly point to the
1123
1308
  closest labelled anomaly point.
1124
1309
 
1310
+ Implementation of https://link.springer.com/article/10.1007/s10618-023-00988-8
1311
+
1312
+ For more information, see the original paper:
1313
+ https://sciendo.com/article/10.2478/ausi-2019-0008
1125
1314
 
1126
1315
  Parameters:
1127
1316
  y_true (np.array):
@@ -1137,7 +1326,8 @@ def temporal_distance(y_true: np.array, y_pred: np.array, distance: int = 0):
1137
1326
  Returns:
1138
1327
  float: The temporal distance.
1139
1328
  """
1140
-
1329
+ validate_binary_inputs(y_true, y_pred)
1330
+
1141
1331
  m = Temporal_Distance(len(y_true),y_true,y_pred,distance=distance)
1142
1332
  return m.get_score()
1143
1333
 
@@ -1145,8 +1335,8 @@ def average_detection_count(y_true: np.array, y_pred: np.array):
1145
1335
  """
1146
1336
  Calculate average detection count for anomaly detection in time series.
1147
1337
 
1148
- This metric computes, for each ground-truth anomalous segment, how many points within that segment
1149
- are predicted as anomalous. It then averages these counts across all true anomaly events,
1338
+ This metric computes, for each ground-truth anomalous segment, the percentage of points within that segment
1339
+ that are predicted as anomalous. It then averages these percentages across all true anomaly events,
1150
1340
  providing an estimate of detection coverage per event.
1151
1341
 
1152
1342
  For more information, see the original paper:
@@ -1162,10 +1352,11 @@ def average_detection_count(y_true: np.array, y_pred: np.array):
1162
1352
  Returns:
1163
1353
  float: The average detection count score.
1164
1354
  """
1165
-
1355
+ validate_binary_inputs(y_true, y_pred)
1356
+
1166
1357
  b = Binary_detection(len(y_true),y_true,y_pred)
1167
1358
  azs = b.get_gt_anomalies_segmentwise()
1168
- a_points = b.get_gt_anomalies_ptwise()
1359
+ a_points = b.get_predicted_anomalies_ptwise()
1169
1360
 
1170
1361
  counts = []
1171
1362
  for az in azs:
@@ -1173,7 +1364,7 @@ def average_detection_count(y_true: np.array, y_pred: np.array):
1173
1364
  for ap in a_points:
1174
1365
  if ap >= az[0] and ap <= az[1]:
1175
1366
  count+=1
1176
- counts.append(count)
1367
+ counts.append(count/(az[1] - az[0] + 1)) # Normalize by segment length
1177
1368
 
1178
1369
  return np.mean(counts)
1179
1370
 
@@ -1182,7 +1373,7 @@ def absolute_detection_distance(y_true: np.array, y_pred: np.array):
1182
1373
  Calculate absolute detection distance for anomaly detection in time series.
1183
1374
 
1184
1375
  This metric computes, for each predicted anomaly point that overlaps a ground-truth anomaly segment,
1185
- the distance from that point to the temporal center of the corresponding segment. It then sums all
1376
+ the relative distance from that point to the temporal center of the corresponding segment. It then sums all
1186
1377
  those distances and divides by the total number of such matching predicted points, yielding the
1187
1378
  mean distance to segment centers for correctly detected points.
1188
1379
 
@@ -1199,17 +1390,19 @@ def absolute_detection_distance(y_true: np.array, y_pred: np.array):
1199
1390
  Returns:
1200
1391
  float: The absolute detection distance.
1201
1392
  """
1202
-
1393
+ validate_binary_inputs(y_true, y_pred)
1394
+
1203
1395
  b = Binary_detection(len(y_true),y_true,y_pred)
1204
1396
  azs = b.get_gt_anomalies_segmentwise()
1205
- a_points = b.get_gt_anomalies_ptwise()
1206
-
1397
+ a_points = b.get_predicted_anomalies_ptwise()
1398
+ if len(a_points) == 0:
1399
+ return float('inf')
1207
1400
  distance = 0
1208
1401
  for az in azs:
1209
1402
  for ap in a_points:
1210
1403
  if ap >= az[0] and ap <= az[1]:
1211
1404
  center = int((az[0] + az[1]) / 2)
1212
- distance+=abs(ap - center)
1405
+ distance+=abs(ap - center)/max(1,int((az[0] + az[1]) / 2))
1213
1406
 
1214
1407
  return distance/len(a_points)
1215
1408
 
@@ -1250,6 +1443,8 @@ def total_detected_in_range(y_true: np.array, y_pred: np.array, k: int):
1250
1443
  Returns:
1251
1444
  float: The total detected in range score.
1252
1445
  """
1446
+ validate_binary_inputs(y_true, y_pred)
1447
+
1253
1448
  if np.sum(y_pred) == 0:
1254
1449
  return 0
1255
1450
  em,da,ma,_ = counting_method(y_true, y_pred, k)
@@ -1294,6 +1489,8 @@ def detection_accuracy_in_range(y_true: np.array, y_pred: np.array, k: int):
1294
1489
  Returns:
1295
1490
  float: The detection accuracy in range score.
1296
1491
  """
1492
+ validate_binary_inputs(y_true, y_pred)
1493
+
1297
1494
  if np.sum(y_pred) == 0:
1298
1495
  return 0
1299
1496
  em,da,_,fa = counting_method(y_true, y_pred, k)
@@ -1347,6 +1544,8 @@ def weighted_detection_difference(y_true: np.array, y_pred: np.array, k: int):
1347
1544
  Returns:
1348
1545
  float: The weighted detection difference.
1349
1546
  """
1547
+ validate_binary_inputs(y_true, y_pred)
1548
+
1350
1549
  if np.sum(y_pred) == 0:
1351
1550
  return 0
1352
1551
 
@@ -1393,6 +1592,8 @@ def binary_pate(y_true: np.array, y_pred: np.array, early: int, delay: int):
1393
1592
  treated as false positives, and missed intervals as false negatives. The final score balances these
1394
1593
  weighted detections into a single measure of performance.
1395
1594
 
1595
+ Implementation of https://arxiv.org/abs/2405.12096
1596
+
1396
1597
  For more information, see the original paper:
1397
1598
  https://arxiv.org/abs/2405.12096
1398
1599
 
@@ -1409,7 +1610,8 @@ def binary_pate(y_true: np.array, y_pred: np.array, early: int, delay: int):
1409
1610
  Returns:
1410
1611
  float: The PATE score.
1411
1612
  """
1412
-
1613
+ validate_binary_inputs(y_true, y_pred)
1614
+
1413
1615
  return PATE(y_true, y_pred, early, delay, binary_scores=True)
1414
1616
 
1415
1617
  def mean_time_to_detect(y_true: np.array, y_pred: np.array):
@@ -1418,13 +1620,13 @@ def mean_time_to_detect(y_true: np.array, y_pred: np.array):
1418
1620
 
1419
1621
  This metric quantifies the average detection delay across all true anomaly events.
1420
1622
  For each ground-truth anomaly segment, let i be the index where the segment starts,
1421
- and let j i be the first index within that segment where the model predicts an anomaly.
1623
+ and let :math:`{j \geq i}` be the first index within that segment where the model predicts an anomaly.
1422
1624
  The detection delay for that event is defined as:
1423
1625
 
1424
1626
  .. math::
1425
- \Delta = j - i
1627
+ \Delta t = j - i
1426
1628
 
1427
- The MTTD is the mean of all such Δ values, one per true anomaly segment, and expresses
1629
+ The MTTD is the mean of all such :math:`{\Delta t}` values, one per true anomaly segment, and expresses
1428
1630
  the average number of time steps between the true onset of an anomaly and its first detection.
1429
1631
 
1430
1632
  Parameters:
@@ -1433,12 +1635,10 @@ def mean_time_to_detect(y_true: np.array, y_pred: np.array):
1433
1635
  y_pred (np.array):
1434
1636
  The predicted binary labels for the time series data.
1435
1637
 
1436
- For more information, see the original paper:
1437
- https://arxiv.org/pdf/2211.05244
1438
-
1439
1638
  Returns:
1440
1639
  float: The mean time to detect.
1441
1640
  """
1641
+ validate_binary_inputs(y_true, y_pred)
1442
1642
 
1443
1643
  b = Binary_detection(len(y_true),y_true,y_pred)
1444
1644
  a_events = b.get_gt_anomalies_segmentwise()