From d138dda5c10e8d472b6a0938aed249b55f9007fa Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 14:23:18 +0200 Subject: [PATCH 1/8] fix test clustering --- aeon/clustering/deep_learning/_ae_fcn.py | 7 +- aeon/clustering/deep_learning/_ae_resnet.py | 7 +- ...test_random_state_deep_learning_cluster.py | 64 +++++++++++-------- aeon/networks/_ae_resnet.py | 7 ++ 4 files changed, 55 insertions(+), 30 deletions(-) diff --git a/aeon/clustering/deep_learning/_ae_fcn.py b/aeon/clustering/deep_learning/_ae_fcn.py index a9f33751ce..1f81832e83 100644 --- a/aeon/clustering/deep_learning/_ae_fcn.py +++ b/aeon/clustering/deep_learning/_ae_fcn.py @@ -331,15 +331,16 @@ def get_test_params(cls, parameter_set="default"): "batch_size": 4, "use_bias": False, "n_layers": 1, - "n_filters": 5, - "kernel_size": 3, + "n_filters": 4, + "kernel_size": 2, "padding": "same", "strides": 1, + "latent_space_dim": 4, "clustering_params": { "distance": "euclidean", "averaging_method": "mean", "n_init": 1, - "max_iter": 30, + "max_iter": 2, }, } diff --git a/aeon/clustering/deep_learning/_ae_resnet.py b/aeon/clustering/deep_learning/_ae_resnet.py index 2d1ccf13e0..d473d0827c 100644 --- a/aeon/clustering/deep_learning/_ae_resnet.py +++ b/aeon/clustering/deep_learning/_ae_resnet.py @@ -40,7 +40,7 @@ class AEResNetClusterer(BaseDeepClusterer): The number of convolution filters for all the convolution layers in the same residual block, if not a list, the same number of filters is used in all convolutions of all residual blocks. - kernel_sizes : int or list of int, default = [8, 5, 3] + kernel_size : int or list of int, default = [8, 5, 3] The kernel size of all the convolution layers in one residual block, if not a list, the same kernel size is used in all convolution layers. strides : int or list of int, default = 1 @@ -352,11 +352,14 @@ def get_test_params(cls, parameter_set="default"): "batch_size": 4, "n_residual_blocks": 1, "n_conv_per_residual_block": 1, + "n_filters": 1, + "kernel_size": 2, + "use_bias": False, "clustering_params": { "distance": "euclidean", "averaging_method": "mean", "n_init": 1, - "max_iter": 30, + "max_iter": 2, }, } diff --git a/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py b/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py index 580d5eccf0..cab43bde8f 100644 --- a/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py +++ b/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py @@ -7,49 +7,63 @@ from aeon.clustering import deep_learning from aeon.testing.data_generation import make_example_3d_numpy +from aeon.utils.validation._dependencies import _check_soft_dependencies __maintainer__ = ["hadifawaz1999"] +_deep_clr_classes = [ + member[1] for member in inspect.getmembers(deep_learning, inspect.isclass) +] + @pytest.mark.skipif( - # not _check_soft_dependencies("tensorflow", severity="none"), - # See Issue #1761 - True, + not _check_soft_dependencies("tensorflow", severity="none"), reason="skip test if required soft dependency not available", ) -def test_random_state_deep_learning_clr(): +@pytest.mark.parametrize("deep_clr", _deep_clr_classes) +def test_random_state_deep_learning_clr(deep_clr): """Test Deep Clusterer seeding.""" - random_state = 42 - - X, _ = make_example_3d_numpy(random_state=random_state) + if not (deep_clr in ["BaseDeepClusterer"]): + random_state = 42 - deep_clr_classes = [ - member[1] for member in inspect.getmembers(deep_learning, inspect.isclass) - ] + X, _ = make_example_3d_numpy(random_state=random_state) - for i in range(len(deep_clr_classes)): - if "BaseDeepClusterer" in str(deep_clr_classes[i]): - continue + test_params = deep_clr.get_test_params()[0] + test_params["random_state"] = random_state - deep_clr1 = deep_clr_classes[i]( - n_clusters=2, random_state=random_state, n_epochs=4 - ) + deep_clr1 = deep_clr(**test_params) deep_clr1.fit(X) - layers1 = deep_clr1.training_model_.layers[1:] + encoder1 = deep_clr1.training_model_.layers[1] + decoder1 = deep_clr1.training_model_.layers[2] + encoder_layers1 = encoder1.layers[1:] + decoder_layers1 = decoder1.layers[1:] - deep_clr2 = deep_clr_classes[i]( - n_clusters=2, random_state=random_state, n_epochs=4 - ) + deep_clr2 = deep_clr(**test_params) deep_clr2.fit(X) - layers2 = deep_clr2.training_model_.layers[1:] + encoder2 = deep_clr2.training_model_.layers[1] + decoder2 = deep_clr2.training_model_.layers[2] + encoder_layers2 = encoder2.layers[1:] + decoder_layers2 = decoder2.layers[1:] + + # test encoders + for i in range(len(encoder_layers1)): + weights1 = encoder_layers1[i].get_weights() + weights2 = encoder_layers2[i].get_weights() + + assert len(weights1) == len(weights2) + + for j in range(len(weights1)): + _weight1 = np.asarray(weights1[j]) + _weight2 = np.asarray(weights2[j]) - assert len(layers1) == len(layers2) + np.testing.assert_almost_equal(_weight1, _weight2, 4) - for i in range(len(layers1)): - weights1 = layers1[i].get_weights() - weights2 = layers2[i].get_weights() + # test decoders + for i in range(len(decoder_layers1)): + weights1 = decoder_layers1[i].get_weights() + weights2 = decoder_layers2[i].get_weights() assert len(weights1) == len(weights2) diff --git a/aeon/networks/_ae_resnet.py b/aeon/networks/_ae_resnet.py index 4578dd8092..158d1ca9a9 100644 --- a/aeon/networks/_ae_resnet.py +++ b/aeon/networks/_ae_resnet.py @@ -138,36 +138,43 @@ def build_network(self, input_shape, **kwargs): self._kernel_size_ = [8, 5, 3] if self.kernel_size is None else self.kernel_size if isinstance(self._n_filters_, list): + assert len(self._n_filters_) == self.n_residual_blocks self._n_filters = self._n_filters_ else: self._n_filters = [self._n_filters_] * self.n_residual_blocks if isinstance(self._kernel_size_, list): + assert len(self._kernel_size_) == self.n_conv_per_residual_block self._kernel_size = self._kernel_size_ else: self._kernel_size = [self._kernel_size_] * self.n_conv_per_residual_block if isinstance(self.strides, list): + assert len(self.strides) == self.n_conv_per_residual_block self._strides = self.strides else: self._strides = [self.strides] * self.n_conv_per_residual_block if isinstance(self.dilation_rate, list): + assert len(self.dilation_rate) == self.n_conv_per_residual_block self._dilation_rate = self.dilation_rate else: self._dilation_rate = [self.dilation_rate] * self.n_conv_per_residual_block if isinstance(self.padding, list): + assert len(self.padding) == self.n_conv_per_residual_block self._padding = self.padding else: self._padding = [self.padding] * self.n_conv_per_residual_block if isinstance(self.activation, list): + assert len(self.activation) == self.n_conv_per_residual_block self._activation = self.activation else: self._activation = [self.activation] * self.n_conv_per_residual_block if isinstance(self.use_bias, list): + assert len(self.use_bias) == self.n_conv_per_residual_block self._use_bias = self.use_bias else: self._use_bias = [self.use_bias] * self.n_conv_per_residual_block From bead7e37a0bdca3ce639422b9ae873b57c2207af Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 14:39:11 +0200 Subject: [PATCH 2/8] fix bug naming test --- .../tests/test_random_state_deep_learning_cluster.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py b/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py index cab43bde8f..d87aa01640 100644 --- a/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py +++ b/aeon/clustering/deep_learning/tests/test_random_state_deep_learning_cluster.py @@ -23,7 +23,7 @@ @pytest.mark.parametrize("deep_clr", _deep_clr_classes) def test_random_state_deep_learning_clr(deep_clr): """Test Deep Clusterer seeding.""" - if not (deep_clr in ["BaseDeepClusterer"]): + if not (deep_clr.__name__ in ["BaseDeepClusterer"]): random_state = 42 X, _ = make_example_3d_numpy(random_state=random_state) From f0e2f862ea3f2703bf02f701dcba5a39b229e557 Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 15:13:02 +0200 Subject: [PATCH 3/8] make classif testing faster --- aeon/classification/deep_learning/_cnn.py | 14 +++++++--- aeon/classification/deep_learning/_encoder.py | 2 ++ .../deep_learning/_inception_time.py | 8 ++++-- .../tests/test_random_state_deep_learning.py | 7 +++-- .../test_saving_loading_deep_learning_cls.py | 26 +++++++++---------- aeon/networks/_encoder.py | 2 -- aeon/networks/_inception.py | 5 +++- 7 files changed, 40 insertions(+), 24 deletions(-) diff --git a/aeon/classification/deep_learning/_cnn.py b/aeon/classification/deep_learning/_cnn.py index 6f8a13a5ae..568522b45b 100644 --- a/aeon/classification/deep_learning/_cnn.py +++ b/aeon/classification/deep_learning/_cnn.py @@ -332,9 +332,12 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, - "avg_pool_size": 4, + "n_layers": 1, + "n_filters": 1, + "kernel_size": 2, + "avg_pool_size": 2, } test_params = [param1] @@ -652,9 +655,12 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, - "avg_pool_size": 4, + "n_layers": 1, + "n_filters": 1, + "kernel_size": 2, + "avg_pool_size": 2, } test_params = [param1] diff --git a/aeon/classification/deep_learning/_encoder.py b/aeon/classification/deep_learning/_encoder.py index 2765c4cbbe..81f1699b12 100644 --- a/aeon/classification/deep_learning/_encoder.py +++ b/aeon/classification/deep_learning/_encoder.py @@ -310,6 +310,8 @@ def get_test_params(cls, parameter_set="default"): "n_epochs": 8, "batch_size": 4, "use_bias": False, + "n_filters": [2], + "kernel_size": [2], "fc_units": 8, "strides": 2, "dropout_proba": 0, diff --git a/aeon/classification/deep_learning/_inception_time.py b/aeon/classification/deep_learning/_inception_time.py index 6b377d565a..6f9af7e3e9 100644 --- a/aeon/classification/deep_learning/_inception_time.py +++ b/aeon/classification/deep_learning/_inception_time.py @@ -749,9 +749,13 @@ def get_test_params(cls, parameter_set="default"): param1 = { "n_epochs": 10, "batch_size": 4, - "kernel_size": 4, + "depth": 1, + "kernel_size": 2, + "n_filters": 1, + "n_conv_per_layer": 1, "use_residual": False, - "use_bottleneck": True, + "use_bottleneck": False, + "use_max_pooling": False, "depth": 1, "use_custom_filters": False, } diff --git a/aeon/classification/deep_learning/tests/test_random_state_deep_learning.py b/aeon/classification/deep_learning/tests/test_random_state_deep_learning.py index b426169cce..09d9dbf0c0 100644 --- a/aeon/classification/deep_learning/tests/test_random_state_deep_learning.py +++ b/aeon/classification/deep_learning/tests/test_random_state_deep_learning.py @@ -37,12 +37,15 @@ def test_random_state_deep_learning_cls(deep_cls): X, y = make_example_3d_numpy(random_state=random_state) - deep_cls1 = deep_cls(random_state=random_state, n_epochs=4) + test_params = deep_cls.get_test_params()[0] + test_params["random_state"] = random_state + + deep_cls1 = deep_cls(**test_params) deep_cls1.fit(X, y) layers1 = deep_cls1.training_model_.layers[1:] - deep_cls2 = deep_cls(random_state=random_state, n_epochs=4) + deep_cls2 = deep_cls(**test_params) deep_cls2.fit(X, y) layers2 = deep_cls2.training_model_.layers[1:] diff --git a/aeon/classification/deep_learning/tests/test_saving_loading_deep_learning_cls.py b/aeon/classification/deep_learning/tests/test_saving_loading_deep_learning_cls.py index d90393a369..72615005a7 100644 --- a/aeon/classification/deep_learning/tests/test_saving_loading_deep_learning_cls.py +++ b/aeon/classification/deep_learning/tests/test_saving_loading_deep_learning_cls.py @@ -46,19 +46,19 @@ def test_saving_loading_deep_learning_cls(deep_cls): X, y = make_example_3d_numpy() - deep_cls_train = deep_cls( - n_epochs=2, - save_best_model=True, - save_last_model=True, - save_init_model=True, - best_file_name=best_file_name, - last_file_name=last_file_name, - init_file_name=init_file_name, - file_path=tmp, - ) + test_params = deep_cls.get_test_params()[0] + test_params["save_best_model"] = True + test_params["save_last_model"] = True + test_params["save_init_model"] = True + test_params["best_file_name"] = best_file_name + test_params["last_file_name"] = last_file_name + test_params["init_file_name"] = init_file_name + test_params["file_path"] = tmp + + deep_cls_train = deep_cls(**test_params) deep_cls_train.fit(X, y) - deep_cls_best = deep_cls() + deep_cls_best = deep_cls(**test_params) deep_cls_best.load_model( model_path=os.path.join(tmp, best_file_name + ".keras"), classes=np.unique(y), @@ -66,7 +66,7 @@ def test_saving_loading_deep_learning_cls(deep_cls): ypred_best = deep_cls_best.predict(X) assert len(ypred_best) == len(y) - deep_cls_last = deep_cls() + deep_cls_last = deep_cls(**test_params) deep_cls_last.load_model( model_path=os.path.join(tmp, last_file_name + ".keras"), classes=np.unique(y), @@ -74,7 +74,7 @@ def test_saving_loading_deep_learning_cls(deep_cls): ypred_last = deep_cls_last.predict(X) assert len(ypred_last) == len(y) - deep_cls_init = deep_cls() + deep_cls_init = deep_cls(**test_params) deep_cls_init.load_model( model_path=os.path.join(tmp, init_file_name + ".keras"), classes=np.unique(y), diff --git a/aeon/networks/_encoder.py b/aeon/networks/_encoder.py index e2423fc03c..33a45cbca9 100644 --- a/aeon/networks/_encoder.py +++ b/aeon/networks/_encoder.py @@ -89,8 +89,6 @@ def build_network(self, input_shape, **kwargs): """ import tensorflow as tf - tf.keras.config.enable_unsafe_deserialization() - self._kernel_size = ( [5, 11, 21] if self.kernel_size is None else self.kernel_size ) diff --git a/aeon/networks/_inception.py b/aeon/networks/_inception.py index 4c8abaa449..eee1c42adc 100644 --- a/aeon/networks/_inception.py +++ b/aeon/networks/_inception.py @@ -340,7 +340,10 @@ def _inception_module( ) conv_list.append(hybrid_layer) - x = tf.keras.layers.Concatenate(axis=2)(conv_list) + if len(conv_list) > 1: + x = tf.keras.layers.Concatenate(axis=2)(conv_list) + else: + x = conv_list[0] x = tf.keras.layers.BatchNormalization()(x) x = tf.keras.layers.Activation(activation=activation)(x) From c29da6a4a8b125a899d4096f85ee9b01ce7bc4c5 Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 17:11:49 +0200 Subject: [PATCH 4/8] try fix encoder network --- aeon/networks/_encoder.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/aeon/networks/_encoder.py b/aeon/networks/_encoder.py index 33a45cbca9..dd4394cf09 100644 --- a/aeon/networks/_encoder.py +++ b/aeon/networks/_encoder.py @@ -117,14 +117,12 @@ def build_network(self, input_shape, **kwargs): # split attention - split_index = self._n_filters[-1] // 2 + split_size1 = int(self._n_filters[-1] // 2) + split_size2 = int(self._n_filters[-1] - split_size1) - attention_multiplier_1 = tf.keras.layers.Softmax()( - tf.keras.layers.Lambda(lambda x: x[:, :, :split_index])(conv) + attention_multiplier_1, attention_multiplier_2 = tf.split( + conv, [split_size1, split_size2], axis=-1 ) - attention_multiplier_2 = tf.keras.layers.Lambda( - lambda x: x[:, :, split_index:] - )(conv) # attention mechanism From 2eb10a39f851ca337bfd6ea56692f0caa545d23c Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 17:29:04 +0200 Subject: [PATCH 5/8] use self attention now --- aeon/networks/_encoder.py | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/aeon/networks/_encoder.py b/aeon/networks/_encoder.py index dd4394cf09..1620b3ca5f 100644 --- a/aeon/networks/_encoder.py +++ b/aeon/networks/_encoder.py @@ -115,20 +115,7 @@ def build_network(self, input_shape, **kwargs): x = conv - # split attention - - split_size1 = int(self._n_filters[-1] // 2) - split_size2 = int(self._n_filters[-1] - split_size1) - - attention_multiplier_1, attention_multiplier_2 = tf.split( - conv, [split_size1, split_size2], axis=-1 - ) - - # attention mechanism - - attention = tf.keras.layers.Multiply()( - [attention_multiplier_1, attention_multiplier_2] - ) + attention = tf.keras.layers.Attention()([conv, conv, conv]) # add fully connected hidden layer From dc6c59753b0db75e1757df0b3eed7897b7c30bce Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Sun, 4 Aug 2024 17:58:31 +0200 Subject: [PATCH 6/8] now regression test --- aeon/classification/deep_learning/_fcn.py | 2 +- .../deep_learning/_inception_time.py | 13 ++++-- aeon/classification/deep_learning/_mlp.py | 2 +- aeon/classification/deep_learning/_resnet.py | 2 +- aeon/regression/deep_learning/_cnn.py | 14 ++++-- aeon/regression/deep_learning/_encoder.py | 2 + aeon/regression/deep_learning/_fcn.py | 4 +- .../deep_learning/_inception_time.py | 21 ++++++--- aeon/regression/deep_learning/_lite_time.py | 6 +-- aeon/regression/deep_learning/_mlp.py | 2 +- aeon/regression/deep_learning/_resnet.py | 2 +- .../tests/test_random_state_deep_regressor.py | 44 ++++++++++--------- .../test_saving_loading_deep_learning_cls.py | 26 +++++------ 13 files changed, 83 insertions(+), 57 deletions(-) diff --git a/aeon/classification/deep_learning/_fcn.py b/aeon/classification/deep_learning/_fcn.py index ea14036b87..8661e40ba4 100644 --- a/aeon/classification/deep_learning/_fcn.py +++ b/aeon/classification/deep_learning/_fcn.py @@ -328,7 +328,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "use_bias": False, "n_layers": 1, diff --git a/aeon/classification/deep_learning/_inception_time.py b/aeon/classification/deep_learning/_inception_time.py index 6f9af7e3e9..4ecab0a33a 100644 --- a/aeon/classification/deep_learning/_inception_time.py +++ b/aeon/classification/deep_learning/_inception_time.py @@ -364,11 +364,16 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_classifiers": 1, - "n_epochs": 10, + "n_classifiers": 2, + "n_epochs": 2, "batch_size": 4, - "kernel_size": 4, + "depth": 1, + "kernel_size": 2, + "n_filters": 1, + "n_conv_per_layer": 1, "use_residual": False, + "use_bottleneck": False, + "use_max_pooling": False, "depth": 1, "use_custom_filters": False, } @@ -747,7 +752,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "depth": 1, "kernel_size": 2, diff --git a/aeon/classification/deep_learning/_mlp.py b/aeon/classification/deep_learning/_mlp.py index 48eb8f711e..692c57d092 100644 --- a/aeon/classification/deep_learning/_mlp.py +++ b/aeon/classification/deep_learning/_mlp.py @@ -293,7 +293,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "use_bias": False, } diff --git a/aeon/classification/deep_learning/_resnet.py b/aeon/classification/deep_learning/_resnet.py index 963faec26b..157bddd657 100644 --- a/aeon/classification/deep_learning/_resnet.py +++ b/aeon/classification/deep_learning/_resnet.py @@ -339,7 +339,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "n_residual_blocks": 1, "n_filters": 5, diff --git a/aeon/regression/deep_learning/_cnn.py b/aeon/regression/deep_learning/_cnn.py index 988e823c63..da65331db0 100644 --- a/aeon/regression/deep_learning/_cnn.py +++ b/aeon/regression/deep_learning/_cnn.py @@ -342,9 +342,12 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, - "avg_pool_size": 4, + "n_layers": 1, + "n_filters": 1, + "kernel_size": 2, + "avg_pool_size": 2, } return [param] @@ -670,9 +673,12 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, - "avg_pool_size": 4, + "n_layers": 1, + "n_filters": 1, + "kernel_size": 2, + "avg_pool_size": 2, } return [param] diff --git a/aeon/regression/deep_learning/_encoder.py b/aeon/regression/deep_learning/_encoder.py index 4b73047c05..543be9dd5f 100644 --- a/aeon/regression/deep_learning/_encoder.py +++ b/aeon/regression/deep_learning/_encoder.py @@ -323,6 +323,8 @@ def get_test_params(cls, parameter_set="default"): "n_epochs": 8, "batch_size": 4, "use_bias": False, + "n_filters": [2], + "kernel_size": [2], "fc_units": 8, "strides": 2, "dropout_proba": 0, diff --git a/aeon/regression/deep_learning/_fcn.py b/aeon/regression/deep_learning/_fcn.py index 374feb5b93..be863cd73c 100644 --- a/aeon/regression/deep_learning/_fcn.py +++ b/aeon/regression/deep_learning/_fcn.py @@ -328,11 +328,11 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "use_bias": False, "n_layers": 1, - "n_filters": 5, + "n_filters": 4, "kernel_size": 3, "padding": "valid", "strides": 2, diff --git a/aeon/regression/deep_learning/_inception_time.py b/aeon/regression/deep_learning/_inception_time.py index a5bd459545..e9a12decc8 100644 --- a/aeon/regression/deep_learning/_inception_time.py +++ b/aeon/regression/deep_learning/_inception_time.py @@ -349,11 +349,16 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_regressors": 1, - "n_epochs": 10, + "n_regressors": 2, + "n_epochs": 2, "batch_size": 4, - "kernel_size": 4, + "depth": 1, + "kernel_size": 2, + "n_filters": 1, + "n_conv_per_layer": 1, "use_residual": False, + "use_bottleneck": False, + "use_max_pooling": False, "depth": 1, "use_custom_filters": False, } @@ -721,11 +726,15 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, - "kernel_size": 4, + "depth": 1, + "kernel_size": 2, + "n_filters": 1, + "n_conv_per_layer": 1, "use_residual": False, - "use_bottleneck": True, + "use_bottleneck": False, + "use_max_pooling": False, "depth": 1, "use_custom_filters": False, } diff --git a/aeon/regression/deep_learning/_lite_time.py b/aeon/regression/deep_learning/_lite_time.py index 5a2079df94..7ca2de5ae7 100644 --- a/aeon/regression/deep_learning/_lite_time.py +++ b/aeon/regression/deep_learning/_lite_time.py @@ -262,8 +262,8 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_regressors": 1, - "n_epochs": 10, + "n_regressors": 2, + "n_epochs": 2, "batch_size": 4, "kernel_size": 4, } @@ -571,7 +571,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param1 = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "kernel_size": 4, } diff --git a/aeon/regression/deep_learning/_mlp.py b/aeon/regression/deep_learning/_mlp.py index cb9907fe7c..f0f084dc87 100644 --- a/aeon/regression/deep_learning/_mlp.py +++ b/aeon/regression/deep_learning/_mlp.py @@ -286,7 +286,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "use_bias": False, } diff --git a/aeon/regression/deep_learning/_resnet.py b/aeon/regression/deep_learning/_resnet.py index 48f2d3c5f8..d611390a31 100644 --- a/aeon/regression/deep_learning/_resnet.py +++ b/aeon/regression/deep_learning/_resnet.py @@ -350,7 +350,7 @@ def get_test_params(cls, parameter_set="default"): `create_test_instance` uses the first (or only) dictionary in `params`. """ param = { - "n_epochs": 10, + "n_epochs": 2, "batch_size": 4, "n_residual_blocks": 1, "n_filters": 5, diff --git a/aeon/regression/deep_learning/tests/test_random_state_deep_regressor.py b/aeon/regression/deep_learning/tests/test_random_state_deep_regressor.py index 3c78367348..c284f6a722 100644 --- a/aeon/regression/deep_learning/tests/test_random_state_deep_regressor.py +++ b/aeon/regression/deep_learning/tests/test_random_state_deep_regressor.py @@ -11,36 +11,40 @@ __maintainer__ = ["hadifawaz1999"] +_deep_rgs_classes = [ + member[1] for member in inspect.getmembers(deep_learning, inspect.isclass) +] + @pytest.mark.skipif( not _check_soft_dependencies(["tensorflow"], severity="none"), reason="skip test if required soft dependency not available", ) -def test_random_state_deep_learning_rgs(): +@pytest.mark.parametrize("deep_rgs", _deep_rgs_classes) +def test_random_state_deep_learning_rgs(deep_rgs): """Test Deep Regressor seeding.""" - random_state = 42 - - X, y = make_example_3d_numpy(random_state=random_state) - - deep_rgs_classes = [ - member[1] for member in inspect.getmembers(deep_learning, inspect.isclass) - ] - - for i in range(len(deep_rgs_classes)): - if ( - "BaseDeepRegressor" in str(deep_rgs_classes[i]) - or "InceptionTimeRegressor" in str(deep_rgs_classes[i]) - or "LITETimeRegressor" in str(deep_rgs_classes[i]) - or "TapNetRegressor" in str(deep_rgs_classes[i]) - ): - continue - - deep_rgs1 = deep_rgs_classes[i](random_state=random_state, n_epochs=4) + if not ( + deep_rgs.__name__ + in [ + "BaseDeepRegressor", + "InceptionTimeRegressor", + "LITETimeRegressor", + "TapNetRegressor", + ] + ): + random_state = 42 + + X, y = make_example_3d_numpy(random_state=random_state) + + test_params = deep_rgs.get_test_params()[0] + test_params["random_state"] = random_state + + deep_rgs1 = deep_rgs(**test_params) deep_rgs1.fit(X, y) layers1 = deep_rgs1.training_model_.layers[1:] - deep_rgs2 = deep_rgs_classes[i](random_state=random_state, n_epochs=4) + deep_rgs2 = deep_rgs(**test_params) deep_rgs2.fit(X, y) layers2 = deep_rgs2.training_model_.layers[1:] diff --git a/aeon/regression/deep_learning/tests/test_saving_loading_deep_learning_cls.py b/aeon/regression/deep_learning/tests/test_saving_loading_deep_learning_cls.py index 736d99baf3..fa0925f853 100644 --- a/aeon/regression/deep_learning/tests/test_saving_loading_deep_learning_cls.py +++ b/aeon/regression/deep_learning/tests/test_saving_loading_deep_learning_cls.py @@ -45,33 +45,33 @@ def test_saving_loading_deep_learning_rgs(deep_rgs): X, y = make_example_3d_numpy() - deep_rgs_train = deep_rgs( - n_epochs=2, - save_best_model=True, - save_last_model=True, - save_init_model=True, - best_file_name=best_file_name, - last_file_name=last_file_name, - init_file_name=init_file_name, - file_path=tmp, - ) + test_params = deep_rgs.get_test_params()[0] + test_params["save_best_model"] = True + test_params["save_last_model"] = True + test_params["save_init_model"] = True + test_params["best_file_name"] = best_file_name + test_params["last_file_name"] = last_file_name + test_params["init_file_name"] = init_file_name + test_params["file_path"] = tmp + + deep_rgs_train = deep_rgs(**test_params) deep_rgs_train.fit(X, y) - deep_rgs_best = deep_rgs() + deep_rgs_best = deep_rgs(**test_params) deep_rgs_best.load_model( model_path=os.path.join(tmp, best_file_name + ".keras"), ) ypred_best = deep_rgs_best.predict(X) assert len(ypred_best) == len(y) - deep_rgs_last = deep_rgs() + deep_rgs_last = deep_rgs(**test_params) deep_rgs_last.load_model( model_path=os.path.join(tmp, last_file_name + ".keras"), ) ypred_last = deep_rgs_last.predict(X) assert len(ypred_last) == len(y) - deep_rgs_init = deep_rgs() + deep_rgs_init = deep_rgs(**test_params) deep_rgs_init.load_model( model_path=os.path.join(tmp, init_file_name + ".keras"), ) From 8e582c5039d1ac112fb3a634070d94da54a68b48 Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Mon, 5 Aug 2024 13:54:06 +0200 Subject: [PATCH 7/8] add dummy cltr option use it in test --- aeon/clustering/deep_learning/_ae_fcn.py | 8 ++------ aeon/clustering/deep_learning/_ae_resnet.py | 8 ++------ aeon/clustering/deep_learning/base.py | 9 +++++++-- 3 files changed, 11 insertions(+), 14 deletions(-) diff --git a/aeon/clustering/deep_learning/_ae_fcn.py b/aeon/clustering/deep_learning/_ae_fcn.py index 1f81832e83..2a379394e1 100644 --- a/aeon/clustering/deep_learning/_ae_fcn.py +++ b/aeon/clustering/deep_learning/_ae_fcn.py @@ -336,12 +336,8 @@ def get_test_params(cls, parameter_set="default"): "padding": "same", "strides": 1, "latent_space_dim": 4, - "clustering_params": { - "distance": "euclidean", - "averaging_method": "mean", - "n_init": 1, - "max_iter": 2, - }, + "clustering_algorithm": "dummy", + "clustering_params": {"strategy": "random"}, } return [param1] diff --git a/aeon/clustering/deep_learning/_ae_resnet.py b/aeon/clustering/deep_learning/_ae_resnet.py index d473d0827c..b968d759e2 100644 --- a/aeon/clustering/deep_learning/_ae_resnet.py +++ b/aeon/clustering/deep_learning/_ae_resnet.py @@ -355,12 +355,8 @@ def get_test_params(cls, parameter_set="default"): "n_filters": 1, "kernel_size": 2, "use_bias": False, - "clustering_params": { - "distance": "euclidean", - "averaging_method": "mean", - "n_init": 1, - "max_iter": 2, - }, + "clustering_algorithm": "dummy", + "clustering_params": {"strategy": "random"}, } test_params = [param] diff --git a/aeon/clustering/deep_learning/base.py b/aeon/clustering/deep_learning/base.py index f5885e8cb1..b2593cf535 100644 --- a/aeon/clustering/deep_learning/base.py +++ b/aeon/clustering/deep_learning/base.py @@ -8,6 +8,7 @@ from aeon.clustering._k_medoids import TimeSeriesKMedoids from aeon.clustering._k_shapes import TimeSeriesKShapes from aeon.clustering.base import BaseClusterer +from aeon.clustering.dummy import DummyClusterer class BaseDeepClusterer(BaseClusterer, ABC): @@ -17,7 +18,7 @@ class BaseDeepClusterer(BaseClusterer, ABC): ---------- n_clusters : int, default=None Number of clusters for the deep learning model. - clustering_algorithm : str, {'kmeans', 'kshape', 'kmedoids'}, + clustering_algorithm : str, {'kmeans', 'kshape', 'kmedoids', 'dummy'}, default="kmeans" The clustering algorithm used in the latent space. Options include: @@ -115,7 +116,11 @@ def _fit_clustering(self, X): else: clustering_params_ = self.clustering_params # clustering_params_["n_clusters"] = self.n_clusters - if self.clustering_algorithm == "kmeans": + if self.clustering_algorithm == "dummy": + self.clusterer = DummyClusterer( + n_clusters=self.n_clusters, **clustering_params_ + ) + elif self.clustering_algorithm == "kmeans": self.clusterer = TimeSeriesKMeans( n_clusters=self.n_clusters, **clustering_params_ ) From 4050ae39c8a0849860586ab449eaddb37d691b10 Mon Sep 17 00:00:00 2001 From: hadifawaz1999 Date: Thu, 8 Aug 2024 10:36:04 +0200 Subject: [PATCH 8/8] add assert error messages --- aeon/networks/_ae_resnet.py | 42 ++++++++++++++++++++++++++++++------- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/aeon/networks/_ae_resnet.py b/aeon/networks/_ae_resnet.py index 158d1ca9a9..2540aef478 100644 --- a/aeon/networks/_ae_resnet.py +++ b/aeon/networks/_ae_resnet.py @@ -138,43 +138,71 @@ def build_network(self, input_shape, **kwargs): self._kernel_size_ = [8, 5, 3] if self.kernel_size is None else self.kernel_size if isinstance(self._n_filters_, list): - assert len(self._n_filters_) == self.n_residual_blocks + assert len(self._n_filters_) == self.n_residual_blocks, ( + f"Number of filters {len(self._n_filters_)} should be" + f" the same as number of residual blocks but is" + f" not: {self.n_residual_blocks}." + ) self._n_filters = self._n_filters_ else: self._n_filters = [self._n_filters_] * self.n_residual_blocks if isinstance(self._kernel_size_, list): - assert len(self._kernel_size_) == self.n_conv_per_residual_block + assert len(self._kernel_size_) == self.n_conv_per_residual_block, ( + f"Number of kernel sizes {len(self._kernel_size_)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._kernel_size = self._kernel_size_ else: self._kernel_size = [self._kernel_size_] * self.n_conv_per_residual_block if isinstance(self.strides, list): - assert len(self.strides) == self.n_conv_per_residual_block + assert len(self.strides) == self.n_conv_per_residual_block, ( + f"Number of strides {len(self.strides)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._strides = self.strides else: self._strides = [self.strides] * self.n_conv_per_residual_block if isinstance(self.dilation_rate, list): - assert len(self.dilation_rate) == self.n_conv_per_residual_block + assert len(self.dilation_rate) == self.n_conv_per_residual_block, ( + f"Number of dilation rates {len(self.dilation_rate)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._dilation_rate = self.dilation_rate else: self._dilation_rate = [self.dilation_rate] * self.n_conv_per_residual_block if isinstance(self.padding, list): - assert len(self.padding) == self.n_conv_per_residual_block + assert len(self.padding) == self.n_conv_per_residual_block, ( + f"Number of paddings {len(self.padding)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._padding = self.padding else: self._padding = [self.padding] * self.n_conv_per_residual_block if isinstance(self.activation, list): - assert len(self.activation) == self.n_conv_per_residual_block + assert len(self.activation) == self.n_conv_per_residual_block, ( + f"Number of activations {len(self.activation)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._activation = self.activation else: self._activation = [self.activation] * self.n_conv_per_residual_block if isinstance(self.use_bias, list): - assert len(self.use_bias) == self.n_conv_per_residual_block + assert len(self.use_bias) == self.n_conv_per_residual_block, ( + f"Number of use biases {len(self.use_bias)} should be" + f" the same as number of convolution layers per block but is" + f" not: {self.n_conv_per_residual_block}." + ) self._use_bias = self.use_bias else: self._use_bias = [self.use_bias] * self.n_conv_per_residual_block