Skip to content

Commit 28f2ffc

Browse files
authored
[REF] Refactor Anomaly Detection Module into Submodules by Algorithm Family (#2694)
* Refactor Anomaly Detection Module into Submodules by Algorithm Family * updated documentation and references * implemented suggested changes * minor changes * added headers for remaining algorithm family * removing tree-based header
1 parent 724cdb0 commit 28f2ffc

39 files changed

+140
-62
lines changed

Diff for: aeon/anomaly_detection/__init__.py

+2-26
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,7 @@
11
"""Time Series Anomaly Detection."""
22

33
__all__ = [
4-
"CBLOF",
5-
"COPOD",
6-
"DWT_MLEAD",
7-
"IsolationForest",
8-
"KMeansAD",
9-
"LeftSTAMPi",
10-
"LOF",
11-
"MERLIN",
12-
"OneClassSVM",
13-
"ROCKAD",
14-
"PyODAdapter",
15-
"STOMP",
16-
"STRAY",
4+
"BaseAnomalyDetector",
175
]
186

19-
from aeon.anomaly_detection._cblof import CBLOF
20-
from aeon.anomaly_detection._copod import COPOD
21-
from aeon.anomaly_detection._dwt_mlead import DWT_MLEAD
22-
from aeon.anomaly_detection._iforest import IsolationForest
23-
from aeon.anomaly_detection._kmeans import KMeansAD
24-
from aeon.anomaly_detection._left_stampi import LeftSTAMPi
25-
from aeon.anomaly_detection._lof import LOF
26-
from aeon.anomaly_detection._merlin import MERLIN
27-
from aeon.anomaly_detection._one_class_svm import OneClassSVM
28-
from aeon.anomaly_detection._pyodadapter import PyODAdapter
29-
from aeon.anomaly_detection._rockad import ROCKAD
30-
from aeon.anomaly_detection._stomp import STOMP
31-
from aeon.anomaly_detection._stray import STRAY
7+
from aeon.anomaly_detection.base import BaseAnomalyDetector

Diff for: aeon/anomaly_detection/distance_based/__init__.py

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
"""Distance basedTime Series Anomaly Detection."""
2+
3+
__all__ = [
4+
"CBLOF",
5+
"KMeansAD",
6+
"LeftSTAMPi",
7+
"LOF",
8+
"MERLIN",
9+
"OneClassSVM",
10+
"STOMP",
11+
]
12+
13+
from aeon.anomaly_detection.distance_based._cblof import CBLOF
14+
from aeon.anomaly_detection.distance_based._kmeans import KMeansAD
15+
from aeon.anomaly_detection.distance_based._left_stampi import LeftSTAMPi
16+
from aeon.anomaly_detection.distance_based._lof import LOF
17+
from aeon.anomaly_detection.distance_based._merlin import MERLIN
18+
from aeon.anomaly_detection.distance_based._one_class_svm import OneClassSVM
19+
from aeon.anomaly_detection.distance_based._stomp import STOMP

Diff for: aeon/anomaly_detection/_cblof.py renamed to aeon/anomaly_detection/distance_based/_cblof.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from aeon.anomaly_detection._pyodadapter import PyODAdapter
10+
from aeon.anomaly_detection.outlier_detection._pyodadapter import PyODAdapter
1111
from aeon.utils.validation._dependencies import _check_soft_dependencies
1212

1313

Diff for: aeon/anomaly_detection/_kmeans.py renamed to aeon/anomaly_detection/distance_based/_kmeans.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ class KMeansAD(BaseAnomalyDetector):
6565
Examples
6666
--------
6767
>>> import numpy as np
68-
>>> from aeon.anomaly_detection import KMeansAD
68+
>>> from aeon.anomaly_detection.distance_based import KMeansAD
6969
>>> X = np.array([1, 2, 3, 4, 1, 2, 3, 3, 2, 8, 9, 8, 1, 2, 3, 4], dtype=np.float64)
7070
>>> detector = KMeansAD(n_clusters=3, window_size=4, stride=1, random_state=0)
7171
>>> detector.fit_predict(X)

Diff for: aeon/anomaly_detection/_left_stampi.py renamed to aeon/anomaly_detection/distance_based/_left_stampi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ class LeftSTAMPi(BaseAnomalyDetector):
4444
Internally,this is applying the incremental approach outlined below.
4545
4646
>>> import numpy as np # doctest: +SKIP
47-
>>> from aeon.anomaly_detection import LeftSTAMPi # doctest: +SKIP
47+
>>> from aeon.anomaly_detection.distance_based import LeftSTAMPi # doctest: +SKIP
4848
>>> X = np.random.default_rng(42).random((10)) # doctest: +SKIP
4949
>>> detector = LeftSTAMPi(window_size=3, n_init_train=3) # doctest: +SKIP
5050
>>> detector.fit_predict(X) # doctest: +SKIP

Diff for: aeon/anomaly_detection/_lof.py renamed to aeon/anomaly_detection/distance_based/_lof.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from aeon.anomaly_detection._pyodadapter import PyODAdapter
10+
from aeon.anomaly_detection.outlier_detection._pyodadapter import PyODAdapter
1111
from aeon.utils.validation._dependencies import _check_soft_dependencies
1212

1313

Diff for: aeon/anomaly_detection/_merlin.py renamed to aeon/anomaly_detection/distance_based/_merlin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ class MERLIN(BaseAnomalyDetector):
4343
Examples
4444
--------
4545
>>> import numpy as np
46-
>>> from aeon.anomaly_detection import MERLIN
46+
>>> from aeon.anomaly_detection.distance_based import MERLIN
4747
>>> X = np.array([1, 2, 3, 4, 1, 2, 3, 4, 2, 3, 4, 5, 1, 2, 3, 4])
4848
>>> detector = MERLIN(min_length=4, max_length=5)
4949
>>> detector.fit_predict(X)

Diff for: aeon/anomaly_detection/_stomp.py renamed to aeon/anomaly_detection/distance_based/_stomp.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ class STOMP(BaseAnomalyDetector):
3838
Examples
3939
--------
4040
>>> import numpy as np
41-
>>> from aeon.anomaly_detection import STOMP # doctest: +SKIP
41+
>>> from aeon.anomaly_detection.distance_based import STOMP # doctest: +SKIP
4242
>>> X = np.random.default_rng(42).random((10, 2), dtype=np.float64)
4343
>>> detector = STOMP(X, window_size=2) # doctest: +SKIP
4444
>>> detector.fit_predict(X, axis=0) # doctest: +SKIP
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Distance based test code."""

Diff for: aeon/anomaly_detection/tests/test_cblof.py renamed to aeon/anomaly_detection/distance_based/tests/test_cblof.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import numpy as np
44
import pytest
55

6-
from aeon.anomaly_detection import CBLOF
6+
from aeon.anomaly_detection.distance_based import CBLOF
77
from aeon.testing.data_generation import make_example_1d_numpy
88
from aeon.utils.validation._dependencies import _check_soft_dependencies
99

Diff for: aeon/anomaly_detection/tests/test_kmeans.py renamed to aeon/anomaly_detection/distance_based/tests/test_kmeans.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77
from sklearn.utils import check_random_state
88

9-
from aeon.anomaly_detection import KMeansAD
9+
from aeon.anomaly_detection.distance_based import KMeansAD
1010

1111

1212
def test_kmeansad_univariate():

Diff for: aeon/anomaly_detection/tests/test_left_stampi.py renamed to aeon/anomaly_detection/distance_based/tests/test_left_stampi.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
import numpy as np
99
import pytest
1010

11-
from aeon.anomaly_detection._left_stampi import LeftSTAMPi
11+
from aeon.anomaly_detection.distance_based._left_stampi import LeftSTAMPi
1212
from aeon.testing.data_generation import make_example_1d_numpy
1313
from aeon.utils.validation._dependencies import _check_soft_dependencies
1414

Diff for: aeon/anomaly_detection/tests/test_lof.py renamed to aeon/anomaly_detection/distance_based/tests/test_lof.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import numpy as np
44
import pytest
55

6-
from aeon.anomaly_detection import LOF
6+
from aeon.anomaly_detection.distance_based import LOF
77
from aeon.testing.data_generation import make_example_1d_numpy
88
from aeon.utils.validation._dependencies import _check_soft_dependencies
99

Diff for: aeon/anomaly_detection/tests/test_merlin.py renamed to aeon/anomaly_detection/distance_based/tests/test_merlin.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import numpy as np
66

7-
from aeon.anomaly_detection import MERLIN
7+
from aeon.anomaly_detection.distance_based import MERLIN
88

99
TEST_DATA = np.array(
1010
[

Diff for: aeon/anomaly_detection/tests/test_one_class_svm.py renamed to aeon/anomaly_detection/distance_based/tests/test_one_class_svm.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55
from sklearn.utils import check_random_state
66

7-
from aeon.anomaly_detection import OneClassSVM
7+
from aeon.anomaly_detection.distance_based import OneClassSVM
88

99

1010
def test_one_class_svm_univariate():

Diff for: aeon/anomaly_detection/tests/test_stomp.py renamed to aeon/anomaly_detection/distance_based/tests/test_stomp.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77
from sklearn.utils import check_random_state
88

9-
from aeon.anomaly_detection import STOMP
9+
from aeon.anomaly_detection.distance_based import STOMP
1010
from aeon.utils.validation._dependencies import _check_soft_dependencies
1111

1212

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""Distribution based Time Series Anomaly Detection."""
2+
3+
__all__ = [
4+
"COPOD",
5+
"DWT_MLEAD",
6+
]
7+
8+
from aeon.anomaly_detection.distribution_based._copod import COPOD
9+
from aeon.anomaly_detection.distribution_based._dwt_mlead import DWT_MLEAD

Diff for: aeon/anomaly_detection/_copod.py renamed to aeon/anomaly_detection/distribution_based/_copod.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from aeon.anomaly_detection._pyodadapter import PyODAdapter
10+
from aeon.anomaly_detection.outlier_detection._pyodadapter import PyODAdapter
1111
from aeon.utils.validation._dependencies import _check_soft_dependencies
1212

1313

Diff for: aeon/anomaly_detection/_dwt_mlead.py renamed to aeon/anomaly_detection/distribution_based/_dwt_mlead.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ class DWT_MLEAD(BaseAnomalyDetector):
7878
Examples
7979
--------
8080
>>> import numpy as np
81-
>>> from aeon.anomaly_detection import DWT_MLEAD
81+
>>> from aeon.anomaly_detection.distribution_based import DWT_MLEAD
8282
>>> X = np.array([1, 2, 3, 4, 1, 2, 3, 3, 2, 8, 9, 8, 1, 2, 3, 4], dtype=np.float64)
8383
>>> detector = DWT_MLEAD(
8484
... start_level=1, quantile_boundary_type='percentile', quantile_epsilon=0.01
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Distribution based test code."""

Diff for: aeon/anomaly_detection/tests/test_copod.py renamed to aeon/anomaly_detection/distribution_based/tests/test_copod.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import numpy as np
44
import pytest
55

6-
from aeon.anomaly_detection import COPOD
6+
from aeon.anomaly_detection.distribution_based import COPOD
77
from aeon.testing.data_generation import make_example_1d_numpy
88
from aeon.utils.validation._dependencies import _check_soft_dependencies
99

Diff for: aeon/anomaly_detection/tests/test_dwt_mlead.py renamed to aeon/anomaly_detection/distribution_based/tests/test_dwt_mlead.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77
from sklearn.utils import check_random_state
88

9-
from aeon.anomaly_detection import DWT_MLEAD
9+
from aeon.anomaly_detection.distribution_based import DWT_MLEAD
1010

1111

1212
def test_dwt_mlead_output():

Diff for: aeon/anomaly_detection/outlier_detection/__init__.py

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
"""Time Series Outlier Detection."""
2+
3+
__all__ = [
4+
"IsolationForest",
5+
"PyODAdapter",
6+
"STRAY",
7+
]
8+
9+
from aeon.anomaly_detection.outlier_detection._iforest import IsolationForest
10+
from aeon.anomaly_detection.outlier_detection._pyodadapter import PyODAdapter
11+
from aeon.anomaly_detection.outlier_detection._stray import STRAY

Diff for: aeon/anomaly_detection/_iforest.py renamed to aeon/anomaly_detection/outlier_detection/_iforest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
import numpy as np
99

10-
from aeon.anomaly_detection._pyodadapter import PyODAdapter
10+
from aeon.anomaly_detection.outlier_detection._pyodadapter import PyODAdapter
1111
from aeon.utils.validation._dependencies import _check_soft_dependencies
1212

1313

Diff for: aeon/anomaly_detection/_pyodadapter.py renamed to aeon/anomaly_detection/outlier_detection/_pyodadapter.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,9 @@ class PyODAdapter(BaseAnomalyDetector):
5959
--------
6060
>>> import numpy as np
6161
>>> from pyod.models.lof import LOF # doctest: +SKIP
62-
>>> from aeon.anomaly_detection import PyODAdapter # doctest: +SKIP
62+
>>> from aeon.anomaly_detection.outlier_detection import (
63+
... PyODAdapter
64+
... ) # doctest: +SKIP
6365
>>> X = np.random.default_rng(42).random((10, 2), dtype=np.float64)
6466
>>> detector = PyODAdapter(LOF(), window_size=2) # doctest: +SKIP
6567
>>> detector.fit_predict(X, axis=0) # doctest: +SKIP

Diff for: aeon/anomaly_detection/_stray.py renamed to aeon/anomaly_detection/outlier_detection/_stray.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ class STRAY(BaseAnomalyDetector):
5454
5555
Examples
5656
--------
57-
>>> from aeon.anomaly_detection import STRAY
57+
>>> from aeon.anomaly_detection.outlier_detection import STRAY
5858
>>> from aeon.datasets import load_airline
5959
>>> import numpy as np
6060
>>> X = load_airline()
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Outlier based test code."""

Diff for: aeon/anomaly_detection/tests/test_iforest.py renamed to aeon/anomaly_detection/outlier_detection/tests/test_iforest.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55
from sklearn.utils import check_random_state
66

7-
from aeon.anomaly_detection import IsolationForest
7+
from aeon.anomaly_detection.outlier_detection import IsolationForest
88
from aeon.utils.validation._dependencies import _check_soft_dependencies
99

1010

Diff for: aeon/anomaly_detection/tests/test_pyod_adapter.py renamed to aeon/anomaly_detection/outlier_detection/tests/test_pyod_adapter.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import pytest
77
from sklearn.utils import check_random_state
88

9-
from aeon.anomaly_detection import PyODAdapter
9+
from aeon.anomaly_detection.outlier_detection import PyODAdapter
1010
from aeon.utils.validation._dependencies import _check_soft_dependencies
1111

1212

Diff for: aeon/anomaly_detection/tests/test_stray.py renamed to aeon/anomaly_detection/outlier_detection/tests/test_stray.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import numpy as np
66
from sklearn.preprocessing import MinMaxScaler
77

8-
from aeon.anomaly_detection import STRAY
8+
from aeon.anomaly_detection.outlier_detection import STRAY
99

1010

1111
def test_default_1D():

Diff for: aeon/anomaly_detection/whole_series/__init__.py

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"""Whole Time Series Anomaly Detection."""
2+
3+
__all__ = [
4+
"ROCKAD",
5+
]
6+
7+
from aeon.anomaly_detection.whole_series._rockad import ROCKAD
File renamed without changes.
+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"""Whole series anomaly detection tests."""

Diff for: aeon/anomaly_detection/tests/test_rockad.py renamed to aeon/anomaly_detection/whole_series/tests/test_rockad.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import pytest
55
from sklearn.utils import check_random_state
66

7-
from aeon.anomaly_detection import ROCKAD
7+
from aeon.anomaly_detection.whole_series import ROCKAD
88

99

1010
def test_rockad_univariate():

Diff for: docs/api_reference/anomaly_detection.rst

+58-8
Original file line numberDiff line numberDiff line change
@@ -13,29 +13,79 @@ Each detector in this module specifies its supported input data format, output d
1313
format, and learning type as an overview table in its documentation. Some detectors
1414
support multiple learning types.
1515

16-
Detectors
17-
---------
16+
.. note::
1817

19-
.. currentmodule:: aeon.anomaly_detection
18+
Not all algorithm families are currently implemented. The documentation includes
19+
placeholders for planned categories which will be supported in future.
20+
21+
Distance-based
22+
--------------
23+
24+
.. currentmodule:: aeon.anomaly_detection.distance_based
2025

2126
.. autosummary::
2227
:toctree: auto_generated/
2328
:template: class.rst
2429

2530
CBLOF
26-
COPOD
27-
DWT_MLEAD
28-
IsolationForest
2931
KMeansAD
3032
LeftSTAMPi
3133
LOF
3234
MERLIN
3335
OneClassSVM
34-
PyODAdapter
35-
ROCKAD
3636
STOMP
37+
38+
Distribution-based
39+
-----------------
40+
41+
.. currentmodule:: aeon.anomaly_detection.distribution_based
42+
43+
.. autosummary::
44+
:toctree: auto_generated/
45+
:template: class.rst
46+
47+
COPOD
48+
DWT_MLEAD
49+
50+
Encoding-based
51+
--------------
52+
53+
The algorithms for this family are not implemented yet.
54+
55+
Forecasting-based
56+
-----------------
57+
58+
The algorithms for this family are not implemented yet.
59+
60+
Outlier-Detection
61+
-----------------
62+
63+
.. currentmodule:: aeon.anomaly_detection.outlier_detection
64+
65+
.. autosummary::
66+
:toctree: auto_generated/
67+
:template: class.rst
68+
69+
IsolationForest
70+
PyODAdapter
3771
STRAY
3872

73+
Reconstruction-based
74+
--------------------
75+
76+
The algorithms for this family are not implemented yet.
77+
78+
Whole-Series
79+
------------
80+
81+
.. currentmodule:: aeon.anomaly_detection.whole_series
82+
83+
.. autosummary::
84+
:toctree: auto_generated/
85+
:template: class.rst
86+
87+
ROCKAD
88+
3989
Base
4090
----
4191

0 commit comments

Comments
 (0)