From 7f6e784524c41aba8bb0627f9d916695c668f127 Mon Sep 17 00:00:00 2001 From: lukas leufen <l.leufen@fz-juelich.de> Date: Thu, 16 Jul 2020 16:13:06 +0200 Subject: [PATCH] updated tests (not all finished yet) --- src/data_handling/iterator.py | 2 +- src/model_modules/model_class.py | 12 ++-- src/run_modules/experiment_setup.py | 3 +- src/run_modules/model_setup.py | 6 +- test/test_data_handling/test_iterator.py | 35 ++++++++-- test/test_model_modules/test_model_class.py | 14 ++-- test/test_modules/test_model_setup.py | 73 +++++++++++++++------ test/test_modules/test_pre_processing.py | 2 +- 8 files changed, 107 insertions(+), 40 deletions(-) diff --git a/src/data_handling/iterator.py b/src/data_handling/iterator.py index 883ba4df..0eec4326 100644 --- a/src/data_handling/iterator.py +++ b/src/data_handling/iterator.py @@ -57,7 +57,7 @@ class KerasIterator(keras.utils.Sequence): def __init__(self, collection: DataCollection, batch_size: int, batch_path: str, shuffle_batches: bool = False, model=None, upsampling=False, name=None): self._collection = collection - batch_path = os.path.join(batch_path, str(name) if name is not None else id(self)) + batch_path = os.path.join(batch_path, str(name if name is not None else id(self))) self._path = os.path.join(batch_path, "%i.pickle") self.batch_size = batch_size self.model = model diff --git a/src/model_modules/model_class.py b/src/model_modules/model_class.py index 535941f8..ca54840c 100644 --- a/src/model_modules/model_class.py +++ b/src/model_modules/model_class.py @@ -341,7 +341,7 @@ class MyLittleModel(AbstractModelClass): Dense layer. """ - def __init__(self, shape_inputs, shape_outputs): + def __init__(self, shape_inputs: list, shape_outputs: list): """ Sets model and loss depending on the given arguments. @@ -350,6 +350,7 @@ class MyLittleModel(AbstractModelClass): """ assert len(shape_inputs) == 1 + assert len(shape_outputs) == 1 super().__init__(shape_inputs[0], shape_outputs[0]) # settings @@ -400,7 +401,7 @@ class MyBranchedModel(AbstractModelClass): Dense layer. """ - def __init__(self, shape_inputs, shape_outputs): + def __init__(self, shape_inputs: list, shape_outputs: list): """ Sets model and loss depending on the given arguments. @@ -409,6 +410,7 @@ class MyBranchedModel(AbstractModelClass): """ assert len(shape_inputs) == 1 + assert len(shape_outputs) == 1 super().__init__(shape_inputs[0], shape_outputs[0]) # settings @@ -457,7 +459,7 @@ class MyBranchedModel(AbstractModelClass): class MyTowerModel(AbstractModelClass): - def __init__(self, shape_inputs, shape_outputs): + def __init__(self, shape_inputs: list, shape_outputs: list): """ Sets model and loss depending on the given arguments. @@ -466,6 +468,7 @@ class MyTowerModel(AbstractModelClass): """ assert len(shape_inputs) == 1 + assert len(shape_outputs) == 1 super().__init__(shape_inputs[0], shape_outputs[0]) # settings @@ -554,7 +557,7 @@ class MyTowerModel(AbstractModelClass): class MyPaperModel(AbstractModelClass): - def __init__(self, shape_inputs, shape_outputs): + def __init__(self, shape_inputs: list, shape_outputs: list): """ Sets model and loss depending on the given arguments. @@ -563,6 +566,7 @@ class MyPaperModel(AbstractModelClass): """ assert len(shape_inputs) == 1 + assert len(shape_outputs) == 1 super().__init__(shape_inputs[0], shape_outputs[0]) # settings diff --git a/src/run_modules/experiment_setup.py b/src/run_modules/experiment_setup.py index 3e471dda..0a9d7119 100644 --- a/src/run_modules/experiment_setup.py +++ b/src/run_modules/experiment_setup.py @@ -301,7 +301,8 @@ class ExperimentSetup(RunEnvironment): self._set_param("sampling", sampling) self._set_param("transformation", transformation, default=DEFAULT_TRANSFORMATION) self._set_param("transformation", None, scope="preprocessing") - self._set_param("data_preparation", data_preparation(), default=CustomDataClass()) + self._set_param("data_preparation", data_preparation() if data_preparation is not None else None, + default=CustomDataClass()) assert isinstance(getattr(self.data_store.get("data_preparation"), "requirements"), property) is False # target diff --git a/src/run_modules/model_setup.py b/src/run_modules/model_setup.py index 5acdac01..7de1c7b6 100644 --- a/src/run_modules/model_setup.py +++ b/src/run_modules/model_setup.py @@ -70,7 +70,7 @@ class ModelSetup(RunEnvironment): def _run(self): # set channels depending on inputs - self._set_channels() + self._set_shapes() # build model graph using settings from my_model_settings() self.build_model() @@ -88,10 +88,8 @@ class ModelSetup(RunEnvironment): # compile model self.compile_model() - def _set_channels(self): + def _set_shapes(self): """Set input and output shapes from train collection.""" - # channels = list(map(lambda x: x[0].shape[-1], self.data_store.get("data_collection", "train")[0].get_X())) - # self.data_store.set("channels", channels, self.scope) shape = list(map(lambda x: x.shape[1:], self.data_store.get("data_collection", "train")[0].get_X())) self.data_store.set("shape_inputs", shape, self.scope) shape = list(map(lambda y: y.shape[1:], self.data_store.get("data_collection", "train")[0].get_Y())) diff --git a/test/test_data_handling/test_iterator.py b/test/test_data_handling/test_iterator.py index 3f1cf683..a4baa3ee 100644 --- a/test/test_data_handling/test_iterator.py +++ b/test/test_data_handling/test_iterator.py @@ -1,9 +1,11 @@ from src.data_handling.iterator import DataCollection, StandardIterator, KerasIterator from src.helpers.testing import PyTestAllEqual +from src.model_modules.model_class import MyLittleModel, MyBranchedModel import numpy as np import pytest +import mock import os import shutil @@ -56,13 +58,13 @@ class DummyData: def __init__(self, number_of_samples=np.random.randint(100, 150)): self.number_of_samples = number_of_samples - def get_X(self): + def get_X(self, upsampling=False, as_numpy=True): X1 = np.random.randint(0, 10, size=(self.number_of_samples, 14, 5)) # samples, window, variables X2 = np.random.randint(21, 30, size=(self.number_of_samples, 10, 2)) # samples, window, variables X3 = np.random.randint(-5, 0, size=(self.number_of_samples, 1, 2)) # samples, window, variables return [X1, X2, X3] - def get_Y(self): + def get_Y(self, upsampling=False, as_numpy=True): Y1 = np.random.randint(0, 10, size=(self.number_of_samples, 5, 1)) # samples, window, variables Y2 = np.random.randint(21, 30, size=(self.number_of_samples, 5, 1)) # samples, window, variables return [Y1, Y2] @@ -88,7 +90,7 @@ class TestKerasIterator: def test_init(self, collection, path): iterator = KerasIterator(collection, 25, path) assert isinstance(iterator._collection, DataCollection) - assert iterator._path == os.path.join(path, "%i.pickle") + assert iterator._path == os.path.join(path, str(id(iterator)), "%i.pickle") assert iterator.batch_size == 25 assert iterator.shuffle is False @@ -149,6 +151,8 @@ class TestKerasIterator: iterator._collection = collection iterator.batch_size = 50 iterator.indexes = [] + iterator.model = None + iterator.upsampling = False iterator._path = os.path.join(path, "%i.pickle") os.makedirs(path) iterator._prepare_batches() @@ -162,6 +166,8 @@ class TestKerasIterator: iterator._collection = DataCollection([DummyData(50)]) iterator.batch_size = 50 iterator.indexes = [] + iterator.model = None + iterator.upsampling = False iterator._path = os.path.join(path, "%i.pickle") os.makedirs(path) iterator._prepare_batches() @@ -198,4 +204,25 @@ class TestKerasIterator: while iterator.indexes == sorted(iterator.indexes): iterator.on_epoch_end() assert iterator.indexes != [0, 1, 2, 3, 4] - assert sorted(iterator.indexes) == [0, 1, 2, 3, 4] \ No newline at end of file + assert sorted(iterator.indexes) == [0, 1, 2, 3, 4] + + def test_get_model_rank_no_model(self): + iterator = object.__new__(KerasIterator) + iterator.model = None + assert iterator._get_model_rank() == 1 + + def test_get_model_rank_single_output_branch(self): + iterator = object.__new__(KerasIterator) + iterator.model = MyLittleModel(shape_inputs=[(14, 1, 2)], shape_outputs=[(3,)]) + assert iterator._get_model_rank() == 1 + + def test_get_model_rank_multiple_output_branch(self): + iterator = object.__new__(KerasIterator) + iterator.model = MyBranchedModel(shape_inputs=[(14, 1, 2)], shape_outputs=[(3,)]) + assert iterator._get_model_rank() == 3 + + def test_get_model_rank_error(self): + iterator = object.__new__(KerasIterator) + iterator.model = mock.MagicMock(return_value=1) + with pytest.raises(TypeError): + iterator._get_model_rank() diff --git a/test/test_model_modules/test_model_class.py b/test/test_model_modules/test_model_class.py index 0ee2eb7e..78adb92f 100644 --- a/test/test_model_modules/test_model_class.py +++ b/test/test_model_modules/test_model_class.py @@ -12,7 +12,7 @@ class Paddings: class AbstractModelSubClass(AbstractModelClass): def __init__(self): - super().__init__() + super().__init__(shape_inputs=(12, 1, 1), shape_outputs=3) self.test_attr = "testAttr" @@ -20,7 +20,7 @@ class TestAbstractModelClass: @pytest.fixture def amc(self): - return AbstractModelClass() + return AbstractModelClass(shape_inputs=(14, 1, 2), shape_outputs=(3,)) @pytest.fixture def amsc(self): @@ -31,6 +31,8 @@ class TestAbstractModelClass: # assert amc.loss is None assert amc.model_name == "AbstractModelClass" assert amc.custom_objects == {} + assert amc.shape_inputs == (14, 1, 2) + assert amc.shape_outputs == 3 def test_model_property(self, amc): amc.model = keras.Model() @@ -179,8 +181,10 @@ class TestAbstractModelClass: assert amc.compile == amc.model.compile def test_get_settings(self, amc, amsc): - assert amc.get_settings() == {"model_name": "AbstractModelClass"} - assert amsc.get_settings() == {"test_attr": "testAttr", "model_name": "AbstractModelSubClass"} + assert amc.get_settings() == {"model_name": "AbstractModelClass", "shape_inputs": (14, 1, 2), + "shape_outputs": 3} + assert amsc.get_settings() == {"test_attr": "testAttr", "model_name": "AbstractModelSubClass", + "shape_inputs": (12, 1, 2), "shape_outputs": 3} def test_custom_objects(self, amc): amc.custom_objects = {"Test": 123} @@ -200,7 +204,7 @@ class TestMyPaperModel: @pytest.fixture def mpm(self): - return MyPaperModel(window_history_size=6, window_lead_time=4, channels=9) + return MyPaperModel(shape_inputs=[(7, 1, 9)], shape_outputs=[(4,)]) def test_init(self, mpm): # check if loss number of loss functions fit to model outputs diff --git a/test/test_modules/test_model_setup.py b/test/test_modules/test_model_setup.py index 6de61b2d..5150eade 100644 --- a/test/test_modules/test_model_setup.py +++ b/test/test_modules/test_model_setup.py @@ -1,9 +1,11 @@ import os +import numpy as np +import shutil import pytest -from src.data_handling import DataPrepJoin -from src.data_handling.data_generator import DataGenerator +from src.data_handling import KerasIterator +from src.data_handling import DataCollection from src.helpers.datastore import EmptyScope from src.model_modules.keras_extensions import CallbackHandler from src.model_modules.model_class import AbstractModelClass, MyLittleModel @@ -29,29 +31,40 @@ class TestModelSetup: RunEnvironment().__del__() @pytest.fixture - def gen(self): - return DataGenerator(os.path.join(os.path.dirname(__file__), 'data'), 'DEBW107', ['o3', 'temp'], - 'datetime', 'variables', 'o3', statistics_per_var={'o3': 'dma8eu', 'temp': 'maximum'}, - data_preparation=DataPrepJoin) + def path(self): + p = os.path.join(os.path.dirname(os.path.abspath(__file__)), "testdata") + shutil.rmtree(p, ignore_errors=True) if os.path.exists(p) else None + yield p + shutil.rmtree(p, ignore_errors=True) @pytest.fixture - def setup_with_gen(self, setup, gen): - setup.data_store.set("generator", gen, "general.train") - setup.data_store.set("window_history_size", gen.window_history_size, "general") - setup.data_store.set("window_lead_time", gen.window_lead_time, "general") - setup.data_store.set("channels", 2, "general") + def keras_iterator(self, path): + coll = [] + for i in range(3): + coll.append(DummyData(50 + i)) + data_coll = DataCollection(collection=coll) + KerasIterator(data_coll, 25, path) + return data_coll + + @pytest.fixture + def setup_with_gen(self, setup, keras_iterator): + setup.data_store.set("data_collection", keras_iterator, "train") + shape_inputs = [keras_iterator[0].get_X()[0].shape[1:]] + setup.data_store.set("shape_inputs", shape_inputs, "model") + shape_outputs = [keras_iterator[0].get_Y()[0].shape[1:]] + setup.data_store.set("shape_outputs", shape_outputs, "model") yield setup RunEnvironment().__del__() @pytest.fixture - def setup_with_gen_tiny(self, setup, gen): - setup.data_store.set("generator", gen, "general.train") + def setup_with_gen_tiny(self, setup, keras_iterator): + setup.data_store.set("data_collection", keras_iterator, "train") yield setup RunEnvironment().__del__() @pytest.fixture def setup_with_model(self, setup): - setup.model = AbstractModelClass() + setup.model = AbstractModelClass(shape_inputs=(12, 1), shape_outputs=2) setup.model.test_param = "42" yield setup RunEnvironment().__del__() @@ -89,14 +102,17 @@ class TestModelSetup: assert setup_with_gen.model is None setup_with_gen.build_model() assert isinstance(setup_with_gen.model, AbstractModelClass) - expected = {"window_history_size", "window_lead_time", "channels", "dropout_rate", "regularizer", "initial_lr", - "optimizer", "activation"} + expected = {"lr_decay", "model_name", "dropout_rate", "regularizer", "initial_lr", "optimizer", "activation", + "shape_inputs", "shape_outputs"} assert expected <= self.current_scope_as_set(setup_with_gen) - def test_set_channels(self, setup_with_gen_tiny): - assert len(setup_with_gen_tiny.data_store.search_name("channels")) == 0 - setup_with_gen_tiny._set_channels() - assert setup_with_gen_tiny.data_store.get("channels", setup_with_gen_tiny.scope) == 2 + def test_set_shapes(self, setup_with_gen_tiny): + assert len(setup_with_gen_tiny.data_store.search_name("shape_inputs")) == 0 + assert len(setup_with_gen_tiny.data_store.search_name("shape_outputs")) == 0 + setup_with_gen_tiny._set_shapes() + assert setup_with_gen_tiny.data_store.get("shape_inputs", setup_with_gen_tiny.scope) == [(14, 1, 5), (10, 1, 2), + (1, 1, 2)] + assert setup_with_gen_tiny.data_store.get("shape_outputs", setup_with_gen_tiny.scope) == [(5,), (3,)] def test_load_weights(self): pass @@ -109,3 +125,20 @@ class TestModelSetup: def test_init(self): pass + + +class DummyData: + + def __init__(self, number_of_samples=np.random.randint(100, 150)): + self.number_of_samples = number_of_samples + + def get_X(self, upsampling=False, as_numpy=True): + X1 = np.random.randint(0, 10, size=(self.number_of_samples, 14, 1, 5)) # samples, window, variables + X2 = np.random.randint(21, 30, size=(self.number_of_samples, 10, 1, 2)) # samples, window, variables + X3 = np.random.randint(-5, 0, size=(self.number_of_samples, 1, 1, 2)) # samples, window, variables + return [X1, X2, X3] + + def get_Y(self, upsampling=False, as_numpy=True): + Y1 = np.random.randint(0, 10, size=(self.number_of_samples, 5)) # samples, window + Y2 = np.random.randint(21, 30, size=(self.number_of_samples, 3)) # samples, window + return [Y1, Y2] \ No newline at end of file diff --git a/test/test_modules/test_pre_processing.py b/test/test_modules/test_pre_processing.py index 0b439e9e..4bf23e6b 100644 --- a/test/test_modules/test_pre_processing.py +++ b/test/test_modules/test_pre_processing.py @@ -42,7 +42,7 @@ class TestPreProcessing: caplog.set_level(logging.INFO) with PreProcessing(): assert caplog.record_tuples[0] == ('root', 20, 'PreProcessing started') - assert caplog.record_tuples[1] == ('root', 20, 'check valid stations started (all)') + assert caplog.record_tuples[1] == ('root', 20, 'check valid stations started (preprocessing)') assert caplog.record_tuples[-1] == ('root', 20, PyTestRegex(r'run for \d+:\d+:\d+ \(hh:mm:ss\) to check 5 ' r'station\(s\). Found 5/5 valid stations.')) RunEnvironment().__del__() -- GitLab