From d6e6275c667138db42e158c27daaead6785e7ded Mon Sep 17 00:00:00 2001 From: Satwik Sai Prakash Sahoo Date: Sun, 16 Nov 2025 16:54:00 +0530 Subject: [PATCH 1/4] Add tests for loading/saving deep clusterers --- .../tests/test_deep_clusterer_io.py | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) create mode 100644 aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py diff --git a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py new file mode 100644 index 0000000000..28a7b399fc --- /dev/null +++ b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py @@ -0,0 +1,48 @@ +"""Tests for saving and loading deep autoencoder clusterers.""" + +import numpy as np +import pytest +from pathlib import Path + +from aeon.clustering.deep_learning._ae_dcnn import AEDCNNClusterer +from aeon.clustering.deep_learning._ae_drnn import AEDRNNClusterer +from aeon.utils.validation._dependencies import _check_soft_dependencies + +from pathlib import Path + +import numpy as np +import pytest + +from aeon.clustering.deep_learning._ae_dcnn import AEDCNNClusterer +from aeon.clustering.deep_learning._ae_drnn import AEDRNNClusterer +from aeon.utils.validation._dependencies import _check_soft_dependencies + + +@pytest.mark.skipif( + not _check_soft_dependencies("tensorflow", severity="none"), + reason="TensorFlow soft dependency not found.", +) +@pytest.mark.parametrize("cls", [AEDRNNClusterer, AEDCNNClusterer]) +def test_deep_clusterer_save_load(tmp_path, cls): + """Test that deep autoencoder clusterers can load a saved Keras model.""" + X = np.random.randn(4, 10, 1).astype(np.float32) + + params = cls._get_test_params()[0] + params["n_epochs"] = 1 + params["save_best_model"] = True + params["file_path"] = str(tmp_path) + "/" + + estimator = params["estimator"] + + model = cls(**params) + model.fit(X) + + saved_files = list(Path(tmp_path).glob("*.keras")) + assert saved_files, "No .keras file was saved during model training" + model_path = str(saved_files[0]) + + loaded = cls(**params) + loaded.load_model(model_path, estimator) + + assert loaded.model_ is not None + assert hasattr(loaded.model_, "predict"), "Loaded keras model is not valid" From ecf4fa67443c14d60aa417c2d404aed930cdf30c Mon Sep 17 00:00:00 2001 From: satwiksps <215063428+satwiksps@users.noreply.github.com> Date: Sun, 16 Nov 2025 11:37:51 +0000 Subject: [PATCH 2/4] Automatic `pre-commit` fixes --- .../deep_learning/tests/test_deep_clusterer_io.py | 8 -------- 1 file changed, 8 deletions(-) diff --git a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py index 28a7b399fc..f4f814a77e 100644 --- a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py +++ b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py @@ -1,13 +1,5 @@ """Tests for saving and loading deep autoencoder clusterers.""" -import numpy as np -import pytest -from pathlib import Path - -from aeon.clustering.deep_learning._ae_dcnn import AEDCNNClusterer -from aeon.clustering.deep_learning._ae_drnn import AEDRNNClusterer -from aeon.utils.validation._dependencies import _check_soft_dependencies - from pathlib import Path import numpy as np From cf7011939a22cf36a83ef6a5df2a7105331e163f Mon Sep 17 00:00:00 2001 From: Satwik Sai Prakash Sahoo Date: Sun, 16 Nov 2025 23:07:19 +0530 Subject: [PATCH 3/4] [MNT] Add comprehensive load/save tests for all deep clusterers --- .../tests/test_deep_clusterer_io.py | 51 +++++++++++-------- 1 file changed, 30 insertions(+), 21 deletions(-) diff --git a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py index f4f814a77e..4b1a5eaa42 100644 --- a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py +++ b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py @@ -1,40 +1,49 @@ -"""Tests for saving and loading deep autoencoder clusterers.""" +"""Tests for loading Keras models in deep autoencoder clusterers.""" +import tempfile from pathlib import Path import numpy as np import pytest +from aeon.clustering.deep_learning._ae_abgru import AEAttentionBiGRUClusterer +from aeon.clustering.deep_learning._ae_bgru import AEBiGRUClusterer from aeon.clustering.deep_learning._ae_dcnn import AEDCNNClusterer from aeon.clustering.deep_learning._ae_drnn import AEDRNNClusterer +from aeon.clustering.deep_learning._ae_fcn import AEFCNClusterer +from aeon.clustering.deep_learning._ae_resnet import AEResNetClusterer from aeon.utils.validation._dependencies import _check_soft_dependencies +ALL_DEEP_CLUSTERERS = [ + AEAttentionBiGRUClusterer, + AEBiGRUClusterer, + AEDCNNClusterer, + AEDRNNClusterer, + AEFCNClusterer, + AEResNetClusterer, +] + @pytest.mark.skipif( not _check_soft_dependencies("tensorflow", severity="none"), - reason="TensorFlow soft dependency not found.", + reason="TensorFlow not installed.", ) -@pytest.mark.parametrize("cls", [AEDRNNClusterer, AEDCNNClusterer]) -def test_deep_clusterer_save_load(tmp_path, cls): - """Test that deep autoencoder clusterers can load a saved Keras model.""" +@pytest.mark.parametrize("cls", ALL_DEEP_CLUSTERERS) +def test_deep_clusterer_load_model(cls): + """Test that all deep autoencoder clusterers load saved Keras models correctly.""" X = np.random.randn(4, 10, 1).astype(np.float32) - params = cls._get_test_params()[0] params["n_epochs"] = 1 params["save_best_model"] = True - params["file_path"] = str(tmp_path) + "/" - estimator = params["estimator"] - - model = cls(**params) - model.fit(X) - - saved_files = list(Path(tmp_path).glob("*.keras")) - assert saved_files, "No .keras file was saved during model training" - model_path = str(saved_files[0]) - - loaded = cls(**params) - loaded.load_model(model_path, estimator) - - assert loaded.model_ is not None - assert hasattr(loaded.model_, "predict"), "Loaded keras model is not valid" + with tempfile.TemporaryDirectory() as tmp: + params["file_path"] = tmp + "/" + model = cls(**params) + model.fit(X) + saved = list(Path(tmp).glob("*.keras")) + assert saved, f"No .keras saved for {cls.__name__}" + model_path = str(saved[0]) + loaded = cls(**params) + loaded.load_model(model_path, estimator) + assert loaded.model_ is not None, f"Loaded model_ is None for {cls.__name__}" + assert hasattr(loaded.model_, "predict"), f"Invalid model_ for {cls.__name__}" From a2be18fadb651e0d71c497ed711280b6d33ba7bd Mon Sep 17 00:00:00 2001 From: Satwik Sai Prakash Sahoo Date: Mon, 17 Nov 2025 12:44:07 +0530 Subject: [PATCH 4/4] Improve deep clusterer load/save tests --- .../deep_learning/tests/test_deep_clusterer_io.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py index 4b1a5eaa42..a47c2c2ba8 100644 --- a/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py +++ b/aeon/clustering/deep_learning/tests/test_deep_clusterer_io.py @@ -35,15 +35,18 @@ def test_deep_clusterer_load_model(cls): params = cls._get_test_params()[0] params["n_epochs"] = 1 params["save_best_model"] = True - estimator = params["estimator"] + with tempfile.TemporaryDirectory() as tmp: params["file_path"] = tmp + "/" model = cls(**params) model.fit(X) + trained_estimator = model._estimator saved = list(Path(tmp).glob("*.keras")) - assert saved, f"No .keras saved for {cls.__name__}" + assert saved, f"No .keras file saved for {cls.__name__}" model_path = str(saved[0]) loaded = cls(**params) - loaded.load_model(model_path, estimator) + loaded.load_model(model_path, trained_estimator) assert loaded.model_ is not None, f"Loaded model_ is None for {cls.__name__}" assert hasattr(loaded.model_, "predict"), f"Invalid model_ for {cls.__name__}" + preds = loaded.predict(X) + assert preds.shape[0] == X.shape[0], f"Predict failed for {cls.__name__}"