From e5d1c8d6e82e1cbb7c4d632efc38d659471e043d Mon Sep 17 00:00:00 2001 From: Nicola Gatto <nicola.gatto@rwth-aachen.de> Date: Mon, 8 Apr 2019 15:36:42 +0200 Subject: [PATCH] Move generated training files --- pom.xml | 2 +- .../cnnarch/gluongenerator/CNNArch2Gluon.java | 3 + .../gluongenerator/CNNTrain2Gluon.java | 11 +- .../resources/templates/gluon/CNNCreator.ftl | 189 ------------------ .../templates/gluon/CNNDataLoader.ftl | 57 ++++++ .../templates/gluon/CNNSupervisedTrainer.ftl | 141 +++++++++++++ .../resources/templates/gluon/CNNTrainer.ftl | 10 +- .../gluongenerator/GenerationTest.java | 12 +- .../target_code/CNNCreator_Alexnet.py | 189 ------------------ .../CNNCreator_CifarClassifierNetwork.py | 189 ------------------ .../resources/target_code/CNNCreator_VGG16.py | 189 ------------------ .../target_code/CNNDataLoader_Alexnet.py | 57 ++++++ .../CNNDataLoader_CifarClassifierNetwork.py | 57 ++++++ .../target_code/CNNDataLoader_VGG16.py | 57 ++++++ .../target_code/CNNTrainer_emptyConfig.py | 10 +- .../target_code/CNNTrainer_fullConfig.py | 10 +- .../target_code/CNNTrainer_simpleConfig.py | 10 +- .../target_code/supervised_trainer.py | 141 +++++++++++++ 18 files changed, 564 insertions(+), 770 deletions(-) create mode 100644 src/main/resources/templates/gluon/CNNDataLoader.ftl create mode 100644 src/main/resources/templates/gluon/CNNSupervisedTrainer.ftl create mode 100644 src/test/resources/target_code/CNNDataLoader_Alexnet.py create mode 100644 src/test/resources/target_code/CNNDataLoader_CifarClassifierNetwork.py create mode 100644 src/test/resources/target_code/CNNDataLoader_VGG16.py create mode 100644 src/test/resources/target_code/supervised_trainer.py diff --git a/pom.xml b/pom.xml index 6b014ce0..0cb7bc93 100644 --- a/pom.xml +++ b/pom.xml @@ -8,7 +8,7 @@ <groupId>de.monticore.lang.monticar</groupId> <artifactId>cnnarch-gluon-generator</artifactId> - <version>0.1.5</version> + <version>0.1.6</version> <!-- == PROJECT DEPENDENCIES ============================================= --> diff --git a/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNArch2Gluon.java b/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNArch2Gluon.java index 652e09db..e0a185a9 100644 --- a/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNArch2Gluon.java +++ b/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNArch2Gluon.java @@ -47,6 +47,9 @@ public class CNNArch2Gluon extends CNNArch2MxNet { temp = archTc.process("CNNNet", Target.PYTHON); fileContentMap.put(temp.getKey(), temp.getValue()); + temp = archTc.process("CNNDataLoader", Target.PYTHON); + fileContentMap.put(temp.getKey(), temp.getValue()); + temp = archTc.process("CNNCreator", Target.PYTHON); fileContentMap.put(temp.getKey(), temp.getValue()); diff --git a/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNTrain2Gluon.java b/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNTrain2Gluon.java index 8be4e1f5..a59beb14 100644 --- a/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNTrain2Gluon.java +++ b/src/main/java/de/monticore/lang/monticar/cnnarch/gluongenerator/CNNTrain2Gluon.java @@ -21,7 +21,14 @@ public class CNNTrain2Gluon extends CNNTrain2MxNet { configDataList.add(configData); Map<String, Object> ftlContext = Collections.singletonMap("configurations", configDataList); - String templateContent = templateConfiguration.processTemplate(ftlContext, "CNNTrainer.ftl"); - return Collections.singletonMap("CNNTrainer_" + getInstanceName() + ".py", templateContent); + Map<String, String> fileContentMap = new HashMap<>(); + + String cnnTrainTemplateContent = templateConfiguration.processTemplate(ftlContext, "CNNTrainer.ftl"); + fileContentMap.put("CNNTrainer_" + getInstanceName() + ".py", cnnTrainTemplateContent); + + String cnnSupervisedTrainerContent = templateConfiguration.processTemplate(ftlContext, "CNNSupervisedTrainer.ftl"); + fileContentMap.put("supervised_trainer.py", cnnSupervisedTrainerContent); + + return fileContentMap; } } \ No newline at end of file diff --git a/src/main/resources/templates/gluon/CNNCreator.ftl b/src/main/resources/templates/gluon/CNNCreator.ftl index a9f6e3c9..fd2e4061 100644 --- a/src/main/resources/templates/gluon/CNNCreator.ftl +++ b/src/main/resources/templates/gluon/CNNCreator.ftl @@ -1,31 +1,12 @@ import mxnet as mx import logging import os -import errno -import shutil -import h5py -import sys -import numpy as np -import time -from mxnet import gluon, autograd, nd from CNNNet_${tc.fullArchitectureName} import Net -@mx.init.register -class MyConstant(mx.init.Initializer): - def __init__(self, value): - super(MyConstant, self).__init__(value=value) - self.value = value - def _init_weight(self, _, arr): - arr[:] = mx.nd.array(self.value) - class ${tc.fileNameWithoutEnding}: - - _data_dir_ = "${tc.dataPath}/" _model_dir_ = "model/${tc.componentName}/" _model_prefix_ = "model" - _input_names_ = [${tc.join(tc.architectureInputs, ",", "'", "'")}] _input_shapes_ = [<#list tc.architecture.inputs as input>(${tc.join(input.definition.type.dimensions, ",")})</#list>] - _output_names_ = [${tc.join(tc.architectureOutputs, ",", "'", "_label'")}] def __init__(self): self.weight_initializer = mx.init.Normal() @@ -60,176 +41,6 @@ class ${tc.fileNameWithoutEnding}: return lastEpoch - def load_data(self, batch_size): - train_h5, test_h5 = self.load_h5_files() - - data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) - data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 - - train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], - train_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - test_iter = None - if test_h5 != None: - test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], - test_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - return train_iter, test_iter, data_mean, data_std - - def load_h5_files(self): - train_h5 = None - test_h5 = None - train_path = self._data_dir_ + "train.h5" - test_path = self._data_dir_ + "test.h5" - if os.path.isfile(train_path): - train_h5 = h5py.File(train_path, 'r') - if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): - logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - test_iter = None - if os.path.isfile(test_path): - test_h5 = h5py.File(test_path, 'r') - if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): - logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - else: - logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") - return train_h5, test_h5 - else: - logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") - sys.exit(1) - - - def train(self, batch_size=64, - num_epoch=10, - eval_metric='acc', - optimizer='adam', - optimizer_params=(('learning_rate', 0.001),), - load_checkpoint=True, - context='gpu', - checkpoint_period=5, - normalize=True): - if context == 'gpu': - mx_context = mx.gpu() - elif context == 'cpu': - mx_context = mx.cpu() - else: - logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") - - if 'weight_decay' in optimizer_params: - optimizer_params['wd'] = optimizer_params['weight_decay'] - del optimizer_params['weight_decay'] - if 'learning_rate_decay' in optimizer_params: - min_learning_rate = 1e-08 - if 'learning_rate_minimum' in optimizer_params: - min_learning_rate = optimizer_params['learning_rate_minimum'] - del optimizer_params['learning_rate_minimum'] - optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( - optimizer_params['step_size'], - factor=optimizer_params['learning_rate_decay'], - stop_factor_lr=min_learning_rate) - del optimizer_params['step_size'] - del optimizer_params['learning_rate_decay'] - - - train_iter, test_iter, data_mean, data_std = self.load_data(batch_size) - if self.net == None: - if normalize: - self.construct(context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) - else: - self.construct(context=mx_context) - - begin_epoch = 0 - if load_checkpoint: - begin_epoch = self.load(mx_context) - else: - if os.path.isdir(self._model_dir_): - shutil.rmtree(self._model_dir_) - - try: - os.makedirs(self._model_dir_) - except OSError: - if not os.path.isdir(self._model_dir_): - raise - - trainer = mx.gluon.Trainer(self.net.collect_params(), optimizer, optimizer_params) - - if self.net.last_layer == 'softmax': - loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() - elif self.net.last_layer == 'sigmoid': - loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() - elif self.net.last_layer == 'linear': - loss_function = mx.gluon.loss.L2Loss() - else: # TODO: Change default? - loss_function = mx.gluon.loss.L2Loss() - logging.warning("Invalid last_layer, defaulting to L2 loss") - - speed_period = 50 - tic = None - - for epoch in range(begin_epoch, begin_epoch + num_epoch): - train_iter.reset() - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - with autograd.record(): - output = self.net(data) - loss = loss_function(output, label) - - loss.backward() - trainer.step(batch_size) - - if tic is None: - tic = time.time() - else: - if batch_i % speed_period == 0: - try: - speed = speed_period * batch_size / (time.time() - tic) - except ZeroDivisionError: - speed = float("inf") - - logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) - - tic = time.time() - - tic = None - - train_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - train_metric_score = metric.get()[1] - - test_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(test_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - test_metric_score = metric.get()[1] - - logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) - - if (epoch - begin_epoch) % checkpoint_period == 0: - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' + str(epoch).zfill(4) + '.params') - - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' - + str(num_epoch + begin_epoch).zfill(4) + '.params') - self.net.export(self._model_dir_ + self._model_prefix_ + '_newest', epoch=0) - - def construct(self, context, data_mean=None, data_std=None): self.net = Net(data_mean=data_mean, data_std=data_std) self.net.collect_params().initialize(self.weight_initializer, ctx=context) diff --git a/src/main/resources/templates/gluon/CNNDataLoader.ftl b/src/main/resources/templates/gluon/CNNDataLoader.ftl new file mode 100644 index 00000000..bc2a6a16 --- /dev/null +++ b/src/main/resources/templates/gluon/CNNDataLoader.ftl @@ -0,0 +1,57 @@ +import os +import h5py +import mxnet as mx +import logging +import sys + +class ${tc.fullArchitectureName}DataLoader: + _input_names_ = [${tc.join(tc.architectureInputs, ",", "'", "'")}] + _output_names_ = [${tc.join(tc.architectureOutputs, ",", "'", "_label'")}] + + def __init__(self): + self._data_dir = "${tc.dataPath}/" + + def load_data(self, batch_size): + train_h5, test_h5 = self.load_h5_files() + + data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) + data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 + + train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], + train_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + test_iter = None + if test_h5 != None: + test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], + test_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + return train_iter, test_iter, data_mean, data_std + + def load_h5_files(self): + train_h5 = None + test_h5 = None + train_path = self._data_dir + "train.h5" + test_path = self._data_dir + "test.h5" + if os.path.isfile(train_path): + train_h5 = h5py.File(train_path, 'r') + if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): + logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + test_iter = None + if os.path.isfile(test_path): + test_h5 = h5py.File(test_path, 'r') + if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): + logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + else: + logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") + return train_h5, test_h5 + else: + logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") + sys.exit(1) \ No newline at end of file diff --git a/src/main/resources/templates/gluon/CNNSupervisedTrainer.ftl b/src/main/resources/templates/gluon/CNNSupervisedTrainer.ftl new file mode 100644 index 00000000..6a471488 --- /dev/null +++ b/src/main/resources/templates/gluon/CNNSupervisedTrainer.ftl @@ -0,0 +1,141 @@ +import mxnet as mx +import logging +import numpy as np +import time +import os +import shutil +from mxnet import gluon, autograd, nd + +class CNNSupervisedTrainer(object): + def __init__(self, data_loader, net_constructor, net=None): + self._data_loader = data_loader + self._net_creator = net_constructor + self._net = net + + def train(self, batch_size=64, + num_epoch=10, + eval_metric='acc', + optimizer='adam', + optimizer_params=(('learning_rate', 0.001),), + load_checkpoint=True, + context='gpu', + checkpoint_period=5, + normalize=True): + if context == 'gpu': + mx_context = mx.gpu() + elif context == 'cpu': + mx_context = mx.cpu() + else: + logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") + + if 'weight_decay' in optimizer_params: + optimizer_params['wd'] = optimizer_params['weight_decay'] + del optimizer_params['weight_decay'] + if 'learning_rate_decay' in optimizer_params: + min_learning_rate = 1e-08 + if 'learning_rate_minimum' in optimizer_params: + min_learning_rate = optimizer_params['learning_rate_minimum'] + del optimizer_params['learning_rate_minimum'] + optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( + optimizer_params['step_size'], + factor=optimizer_params['learning_rate_decay'], + stop_factor_lr=min_learning_rate) + del optimizer_params['step_size'] + del optimizer_params['learning_rate_decay'] + + + train_iter, test_iter, data_mean, data_std = self._data_loader.load_data(batch_size) + if self._net is None: + if normalize: + self._net_creator.construct( + context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) + else: + self._net_creator.construct(context=mx_context) + + begin_epoch = 0 + if load_checkpoint: + begin_epoch = self._net_creator.load(mx_context) + else: + if os.path.isdir(self._net_creator._model_dir_): + shutil.rmtree(self._net_creator._model_dir_) + + self._net = self._net_creator.net + + try: + os.makedirs(self._net_creator._model_dir_) + except OSError: + if not os.path.isdir(self._net_creator._model_dir_): + raise + + trainer = mx.gluon.Trainer(self._net.collect_params(), optimizer, optimizer_params) + + if self._net.last_layer == 'softmax': + loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() + elif self._net.last_layer == 'sigmoid': + loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() + elif self._net.last_layer == 'linear': + loss_function = mx.gluon.loss.L2Loss() + else: # TODO: Change default? + loss_function = mx.gluon.loss.L2Loss() + logging.warning("Invalid last_layer, defaulting to L2 loss") + + speed_period = 50 + tic = None + + for epoch in range(begin_epoch, begin_epoch + num_epoch): + train_iter.reset() + for batch_i, batch in enumerate(train_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + with autograd.record(): + output = self._net(data) + loss = loss_function(output, label) + + loss.backward() + trainer.step(batch_size) + + if tic is None: + tic = time.time() + else: + if batch_i % speed_period == 0: + try: + speed = speed_period * batch_size / (time.time() - tic) + except ZeroDivisionError: + speed = float("inf") + + logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) + + tic = time.time() + + tic = None + + train_iter.reset() + metric = mx.metric.create(eval_metric) + for batch_i, batch in enumerate(train_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + output = self._net(data) + predictions = mx.nd.argmax(output, axis=1) + metric.update(preds=predictions, labels=label) + train_metric_score = metric.get()[1] + + test_iter.reset() + metric = mx.metric.create(eval_metric) + for batch_i, batch in enumerate(test_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + output = self._net(data) + predictions = mx.nd.argmax(output, axis=1) + metric.update(preds=predictions, labels=label) + test_metric_score = metric.get()[1] + + logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) + + if (epoch - begin_epoch) % checkpoint_period == 0: + self._net.save_parameters(self.parameter_path() + '-' + str(epoch).zfill(4) + '.params') + + self._net.save_parameters(self.parameter_path() + '-' + str(num_epoch + begin_epoch).zfill(4) + '.params') + self._net.export(self.parameter_path() + '_newest', epoch=0) + + def parameter_path(self): + return self._net_creator._model_dir_ + self._net_creator._model_prefix_ \ No newline at end of file diff --git a/src/main/resources/templates/gluon/CNNTrainer.ftl b/src/main/resources/templates/gluon/CNNTrainer.ftl index de2e1fec..cca29dbe 100644 --- a/src/main/resources/templates/gluon/CNNTrainer.ftl +++ b/src/main/resources/templates/gluon/CNNTrainer.ftl @@ -1,7 +1,9 @@ import logging import mxnet as mx +import supervised_trainer <#list configurations as config> import CNNCreator_${config.instanceName} +import CNNDataLoader_${config.instanceName} </#list> if __name__ == "__main__": @@ -11,8 +13,12 @@ if __name__ == "__main__": logger.addHandler(handler) <#list configurations as config> - ${config.instanceName} = CNNCreator_${config.instanceName}.CNNCreator_${config.instanceName}() - ${config.instanceName}.train( + ${config.instanceName}_creator = CNNCreator_${config.instanceName}.CNNCreator_${config.instanceName}() + ${config.instanceName}_loader = CNNDataLoader_${config.instanceName}.${config.instanceName}DataLoader() + ${config.instanceName}_trainer = supervised_trainer.CNNSupervisedTrainer(${config.instanceName}_loader, + ${config.instanceName}_creator) + + ${config.instanceName}_trainer.train( <#if (config.batchSize)??> batch_size=${config.batchSize}, </#if> diff --git a/src/test/java/de/monticore/lang/monticar/cnnarch/gluongenerator/GenerationTest.java b/src/test/java/de/monticore/lang/monticar/cnnarch/gluongenerator/GenerationTest.java index 30e242da..545ad921 100644 --- a/src/test/java/de/monticore/lang/monticar/cnnarch/gluongenerator/GenerationTest.java +++ b/src/test/java/de/monticore/lang/monticar/cnnarch/gluongenerator/GenerationTest.java @@ -54,6 +54,7 @@ public class GenerationTest extends AbstractSymtabTest { Arrays.asList( "CNNCreator_CifarClassifierNetwork.py", "CNNNet_CifarClassifierNetwork.py", + "CNNDataLoader_CifarClassifierNetwork.py", "CNNPredictor_CifarClassifierNetwork.h", "execute_CifarClassifierNetwork", "CNNBufferFile.h")); @@ -72,6 +73,7 @@ public class GenerationTest extends AbstractSymtabTest { Arrays.asList( "CNNCreator_Alexnet.py", "CNNNet_Alexnet.py", + "CNNDataLoader_Alexnet.py", "CNNPredictor_Alexnet.h", "execute_Alexnet")); } @@ -89,6 +91,7 @@ public class GenerationTest extends AbstractSymtabTest { Arrays.asList( "CNNCreator_VGG16.py", "CNNNet_VGG16.py", + "CNNDataLoader_VGG16.py", "CNNPredictor_VGG16.h", "execute_VGG16")); } @@ -130,7 +133,8 @@ public class GenerationTest extends AbstractSymtabTest { Paths.get("./target/generated-sources-cnnarch"), Paths.get("./src/test/resources/target_code"), Arrays.asList( - "CNNTrainer_fullConfig.py")); + "CNNTrainer_fullConfig.py", + "supervised_trainer.py")); } @Test @@ -146,7 +150,8 @@ public class GenerationTest extends AbstractSymtabTest { Paths.get("./target/generated-sources-cnnarch"), Paths.get("./src/test/resources/target_code"), Arrays.asList( - "CNNTrainer_simpleConfig.py")); + "CNNTrainer_simpleConfig.py", + "supervised_trainer.py")); } @Test @@ -161,7 +166,8 @@ public class GenerationTest extends AbstractSymtabTest { Paths.get("./target/generated-sources-cnnarch"), Paths.get("./src/test/resources/target_code"), Arrays.asList( - "CNNTrainer_emptyConfig.py")); + "CNNTrainer_emptyConfig.py", + "supervised_trainer.py")); } diff --git a/src/test/resources/target_code/CNNCreator_Alexnet.py b/src/test/resources/target_code/CNNCreator_Alexnet.py index 361567e2..1b2befae 100644 --- a/src/test/resources/target_code/CNNCreator_Alexnet.py +++ b/src/test/resources/target_code/CNNCreator_Alexnet.py @@ -1,31 +1,12 @@ import mxnet as mx import logging import os -import errno -import shutil -import h5py -import sys -import numpy as np -import time -from mxnet import gluon, autograd, nd from CNNNet_Alexnet import Net -@mx.init.register -class MyConstant(mx.init.Initializer): - def __init__(self, value): - super(MyConstant, self).__init__(value=value) - self.value = value - def _init_weight(self, _, arr): - arr[:] = mx.nd.array(self.value) - class CNNCreator_Alexnet: - - _data_dir_ = "data/Alexnet/" _model_dir_ = "model/Alexnet/" _model_prefix_ = "model" - _input_names_ = ['data'] _input_shapes_ = [(3,224,224)] - _output_names_ = ['predictions_label'] def __init__(self): self.weight_initializer = mx.init.Normal() @@ -60,176 +41,6 @@ class CNNCreator_Alexnet: return lastEpoch - def load_data(self, batch_size): - train_h5, test_h5 = self.load_h5_files() - - data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) - data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 - - train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], - train_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - test_iter = None - if test_h5 != None: - test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], - test_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - return train_iter, test_iter, data_mean, data_std - - def load_h5_files(self): - train_h5 = None - test_h5 = None - train_path = self._data_dir_ + "train.h5" - test_path = self._data_dir_ + "test.h5" - if os.path.isfile(train_path): - train_h5 = h5py.File(train_path, 'r') - if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): - logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - test_iter = None - if os.path.isfile(test_path): - test_h5 = h5py.File(test_path, 'r') - if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): - logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - else: - logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") - return train_h5, test_h5 - else: - logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") - sys.exit(1) - - - def train(self, batch_size=64, - num_epoch=10, - eval_metric='acc', - optimizer='adam', - optimizer_params=(('learning_rate', 0.001),), - load_checkpoint=True, - context='gpu', - checkpoint_period=5, - normalize=True): - if context == 'gpu': - mx_context = mx.gpu() - elif context == 'cpu': - mx_context = mx.cpu() - else: - logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") - - if 'weight_decay' in optimizer_params: - optimizer_params['wd'] = optimizer_params['weight_decay'] - del optimizer_params['weight_decay'] - if 'learning_rate_decay' in optimizer_params: - min_learning_rate = 1e-08 - if 'learning_rate_minimum' in optimizer_params: - min_learning_rate = optimizer_params['learning_rate_minimum'] - del optimizer_params['learning_rate_minimum'] - optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( - optimizer_params['step_size'], - factor=optimizer_params['learning_rate_decay'], - stop_factor_lr=min_learning_rate) - del optimizer_params['step_size'] - del optimizer_params['learning_rate_decay'] - - - train_iter, test_iter, data_mean, data_std = self.load_data(batch_size) - if self.net == None: - if normalize: - self.construct(context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) - else: - self.construct(context=mx_context) - - begin_epoch = 0 - if load_checkpoint: - begin_epoch = self.load(mx_context) - else: - if os.path.isdir(self._model_dir_): - shutil.rmtree(self._model_dir_) - - try: - os.makedirs(self._model_dir_) - except OSError: - if not os.path.isdir(self._model_dir_): - raise - - trainer = mx.gluon.Trainer(self.net.collect_params(), optimizer, optimizer_params) - - if self.net.last_layer == 'softmax': - loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() - elif self.net.last_layer == 'sigmoid': - loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() - elif self.net.last_layer == 'linear': - loss_function = mx.gluon.loss.L2Loss() - else: # TODO: Change default? - loss_function = mx.gluon.loss.L2Loss() - logging.warning("Invalid last_layer, defaulting to L2 loss") - - speed_period = 50 - tic = None - - for epoch in range(begin_epoch, begin_epoch + num_epoch): - train_iter.reset() - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - with autograd.record(): - output = self.net(data) - loss = loss_function(output, label) - - loss.backward() - trainer.step(batch_size) - - if tic is None: - tic = time.time() - else: - if batch_i % speed_period == 0: - try: - speed = speed_period * batch_size / (time.time() - tic) - except ZeroDivisionError: - speed = float("inf") - - logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) - - tic = time.time() - - tic = None - - train_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - train_metric_score = metric.get()[1] - - test_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(test_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - test_metric_score = metric.get()[1] - - logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) - - if (epoch - begin_epoch) % checkpoint_period == 0: - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' + str(epoch).zfill(4) + '.params') - - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' - + str(num_epoch + begin_epoch).zfill(4) + '.params') - self.net.export(self._model_dir_ + self._model_prefix_ + '_newest', epoch=0) - - def construct(self, context, data_mean=None, data_std=None): self.net = Net(data_mean=data_mean, data_std=data_std) self.net.collect_params().initialize(self.weight_initializer, ctx=context) diff --git a/src/test/resources/target_code/CNNCreator_CifarClassifierNetwork.py b/src/test/resources/target_code/CNNCreator_CifarClassifierNetwork.py index 65b8a87c..5d63b10b 100644 --- a/src/test/resources/target_code/CNNCreator_CifarClassifierNetwork.py +++ b/src/test/resources/target_code/CNNCreator_CifarClassifierNetwork.py @@ -1,31 +1,12 @@ import mxnet as mx import logging import os -import errno -import shutil -import h5py -import sys -import numpy as np -import time -from mxnet import gluon, autograd, nd from CNNNet_CifarClassifierNetwork import Net -@mx.init.register -class MyConstant(mx.init.Initializer): - def __init__(self, value): - super(MyConstant, self).__init__(value=value) - self.value = value - def _init_weight(self, _, arr): - arr[:] = mx.nd.array(self.value) - class CNNCreator_CifarClassifierNetwork: - - _data_dir_ = "data/CifarClassifierNetwork/" _model_dir_ = "model/CifarClassifierNetwork/" _model_prefix_ = "model" - _input_names_ = ['data'] _input_shapes_ = [(3,32,32)] - _output_names_ = ['softmax_label'] def __init__(self): self.weight_initializer = mx.init.Normal() @@ -60,176 +41,6 @@ class CNNCreator_CifarClassifierNetwork: return lastEpoch - def load_data(self, batch_size): - train_h5, test_h5 = self.load_h5_files() - - data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) - data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 - - train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], - train_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - test_iter = None - if test_h5 != None: - test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], - test_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - return train_iter, test_iter, data_mean, data_std - - def load_h5_files(self): - train_h5 = None - test_h5 = None - train_path = self._data_dir_ + "train.h5" - test_path = self._data_dir_ + "test.h5" - if os.path.isfile(train_path): - train_h5 = h5py.File(train_path, 'r') - if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): - logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - test_iter = None - if os.path.isfile(test_path): - test_h5 = h5py.File(test_path, 'r') - if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): - logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - else: - logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") - return train_h5, test_h5 - else: - logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") - sys.exit(1) - - - def train(self, batch_size=64, - num_epoch=10, - eval_metric='acc', - optimizer='adam', - optimizer_params=(('learning_rate', 0.001),), - load_checkpoint=True, - context='gpu', - checkpoint_period=5, - normalize=True): - if context == 'gpu': - mx_context = mx.gpu() - elif context == 'cpu': - mx_context = mx.cpu() - else: - logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") - - if 'weight_decay' in optimizer_params: - optimizer_params['wd'] = optimizer_params['weight_decay'] - del optimizer_params['weight_decay'] - if 'learning_rate_decay' in optimizer_params: - min_learning_rate = 1e-08 - if 'learning_rate_minimum' in optimizer_params: - min_learning_rate = optimizer_params['learning_rate_minimum'] - del optimizer_params['learning_rate_minimum'] - optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( - optimizer_params['step_size'], - factor=optimizer_params['learning_rate_decay'], - stop_factor_lr=min_learning_rate) - del optimizer_params['step_size'] - del optimizer_params['learning_rate_decay'] - - - train_iter, test_iter, data_mean, data_std = self.load_data(batch_size) - if self.net == None: - if normalize: - self.construct(context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) - else: - self.construct(context=mx_context) - - begin_epoch = 0 - if load_checkpoint: - begin_epoch = self.load(mx_context) - else: - if os.path.isdir(self._model_dir_): - shutil.rmtree(self._model_dir_) - - try: - os.makedirs(self._model_dir_) - except OSError: - if not os.path.isdir(self._model_dir_): - raise - - trainer = mx.gluon.Trainer(self.net.collect_params(), optimizer, optimizer_params) - - if self.net.last_layer == 'softmax': - loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() - elif self.net.last_layer == 'sigmoid': - loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() - elif self.net.last_layer == 'linear': - loss_function = mx.gluon.loss.L2Loss() - else: # TODO: Change default? - loss_function = mx.gluon.loss.L2Loss() - logging.warning("Invalid last_layer, defaulting to L2 loss") - - speed_period = 50 - tic = None - - for epoch in range(begin_epoch, begin_epoch + num_epoch): - train_iter.reset() - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - with autograd.record(): - output = self.net(data) - loss = loss_function(output, label) - - loss.backward() - trainer.step(batch_size) - - if tic is None: - tic = time.time() - else: - if batch_i % speed_period == 0: - try: - speed = speed_period * batch_size / (time.time() - tic) - except ZeroDivisionError: - speed = float("inf") - - logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) - - tic = time.time() - - tic = None - - train_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - train_metric_score = metric.get()[1] - - test_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(test_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - test_metric_score = metric.get()[1] - - logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) - - if (epoch - begin_epoch) % checkpoint_period == 0: - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' + str(epoch).zfill(4) + '.params') - - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' - + str(num_epoch + begin_epoch).zfill(4) + '.params') - self.net.export(self._model_dir_ + self._model_prefix_ + '_newest', epoch=0) - - def construct(self, context, data_mean=None, data_std=None): self.net = Net(data_mean=data_mean, data_std=data_std) self.net.collect_params().initialize(self.weight_initializer, ctx=context) diff --git a/src/test/resources/target_code/CNNCreator_VGG16.py b/src/test/resources/target_code/CNNCreator_VGG16.py index b30f2dcf..af1eed2b 100644 --- a/src/test/resources/target_code/CNNCreator_VGG16.py +++ b/src/test/resources/target_code/CNNCreator_VGG16.py @@ -1,31 +1,12 @@ import mxnet as mx import logging import os -import errno -import shutil -import h5py -import sys -import numpy as np -import time -from mxnet import gluon, autograd, nd from CNNNet_VGG16 import Net -@mx.init.register -class MyConstant(mx.init.Initializer): - def __init__(self, value): - super(MyConstant, self).__init__(value=value) - self.value = value - def _init_weight(self, _, arr): - arr[:] = mx.nd.array(self.value) - class CNNCreator_VGG16: - - _data_dir_ = "data/VGG16/" _model_dir_ = "model/VGG16/" _model_prefix_ = "model" - _input_names_ = ['data'] _input_shapes_ = [(3,224,224)] - _output_names_ = ['predictions_label'] def __init__(self): self.weight_initializer = mx.init.Normal() @@ -60,176 +41,6 @@ class CNNCreator_VGG16: return lastEpoch - def load_data(self, batch_size): - train_h5, test_h5 = self.load_h5_files() - - data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) - data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 - - train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], - train_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - test_iter = None - if test_h5 != None: - test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], - test_h5[self._output_names_[0]], - batch_size=batch_size, - data_name=self._input_names_[0], - label_name=self._output_names_[0]) - return train_iter, test_iter, data_mean, data_std - - def load_h5_files(self): - train_h5 = None - test_h5 = None - train_path = self._data_dir_ + "train.h5" - test_path = self._data_dir_ + "test.h5" - if os.path.isfile(train_path): - train_h5 = h5py.File(train_path, 'r') - if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): - logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - test_iter = None - if os.path.isfile(test_path): - test_h5 = h5py.File(test_path, 'r') - if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): - logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " - + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") - sys.exit(1) - else: - logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") - return train_h5, test_h5 - else: - logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") - sys.exit(1) - - - def train(self, batch_size=64, - num_epoch=10, - eval_metric='acc', - optimizer='adam', - optimizer_params=(('learning_rate', 0.001),), - load_checkpoint=True, - context='gpu', - checkpoint_period=5, - normalize=True): - if context == 'gpu': - mx_context = mx.gpu() - elif context == 'cpu': - mx_context = mx.cpu() - else: - logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") - - if 'weight_decay' in optimizer_params: - optimizer_params['wd'] = optimizer_params['weight_decay'] - del optimizer_params['weight_decay'] - if 'learning_rate_decay' in optimizer_params: - min_learning_rate = 1e-08 - if 'learning_rate_minimum' in optimizer_params: - min_learning_rate = optimizer_params['learning_rate_minimum'] - del optimizer_params['learning_rate_minimum'] - optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( - optimizer_params['step_size'], - factor=optimizer_params['learning_rate_decay'], - stop_factor_lr=min_learning_rate) - del optimizer_params['step_size'] - del optimizer_params['learning_rate_decay'] - - - train_iter, test_iter, data_mean, data_std = self.load_data(batch_size) - if self.net == None: - if normalize: - self.construct(context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) - else: - self.construct(context=mx_context) - - begin_epoch = 0 - if load_checkpoint: - begin_epoch = self.load(mx_context) - else: - if os.path.isdir(self._model_dir_): - shutil.rmtree(self._model_dir_) - - try: - os.makedirs(self._model_dir_) - except OSError: - if not os.path.isdir(self._model_dir_): - raise - - trainer = mx.gluon.Trainer(self.net.collect_params(), optimizer, optimizer_params) - - if self.net.last_layer == 'softmax': - loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() - elif self.net.last_layer == 'sigmoid': - loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() - elif self.net.last_layer == 'linear': - loss_function = mx.gluon.loss.L2Loss() - else: # TODO: Change default? - loss_function = mx.gluon.loss.L2Loss() - logging.warning("Invalid last_layer, defaulting to L2 loss") - - speed_period = 50 - tic = None - - for epoch in range(begin_epoch, begin_epoch + num_epoch): - train_iter.reset() - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - with autograd.record(): - output = self.net(data) - loss = loss_function(output, label) - - loss.backward() - trainer.step(batch_size) - - if tic is None: - tic = time.time() - else: - if batch_i % speed_period == 0: - try: - speed = speed_period * batch_size / (time.time() - tic) - except ZeroDivisionError: - speed = float("inf") - - logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) - - tic = time.time() - - tic = None - - train_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(train_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - train_metric_score = metric.get()[1] - - test_iter.reset() - metric = mx.metric.create(eval_metric) - for batch_i, batch in enumerate(test_iter): - data = batch.data[0].as_in_context(mx_context) - label = batch.label[0].as_in_context(mx_context) - output = self.net(data) - predictions = mx.nd.argmax(output, axis=1) - metric.update(preds=predictions, labels=label) - test_metric_score = metric.get()[1] - - logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) - - if (epoch - begin_epoch) % checkpoint_period == 0: - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' + str(epoch).zfill(4) + '.params') - - self.net.save_parameters(self._model_dir_ + self._model_prefix_ + '-' - + str(num_epoch + begin_epoch).zfill(4) + '.params') - self.net.export(self._model_dir_ + self._model_prefix_ + '_newest', epoch=0) - - def construct(self, context, data_mean=None, data_std=None): self.net = Net(data_mean=data_mean, data_std=data_std) self.net.collect_params().initialize(self.weight_initializer, ctx=context) diff --git a/src/test/resources/target_code/CNNDataLoader_Alexnet.py b/src/test/resources/target_code/CNNDataLoader_Alexnet.py new file mode 100644 index 00000000..264e219f --- /dev/null +++ b/src/test/resources/target_code/CNNDataLoader_Alexnet.py @@ -0,0 +1,57 @@ +import os +import h5py +import mxnet as mx +import logging +import sys + +class AlexnetDataLoader: + _input_names_ = ['data'] + _output_names_ = ['predictions_label'] + + def __init__(self): + self._data_dir = "data/Alexnet/" + + def load_data(self, batch_size): + train_h5, test_h5 = self.load_h5_files() + + data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) + data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 + + train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], + train_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + test_iter = None + if test_h5 != None: + test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], + test_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + return train_iter, test_iter, data_mean, data_std + + def load_h5_files(self): + train_h5 = None + test_h5 = None + train_path = self._data_dir + "train.h5" + test_path = self._data_dir + "test.h5" + if os.path.isfile(train_path): + train_h5 = h5py.File(train_path, 'r') + if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): + logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + test_iter = None + if os.path.isfile(test_path): + test_h5 = h5py.File(test_path, 'r') + if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): + logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + else: + logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") + return train_h5, test_h5 + else: + logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") + sys.exit(1) \ No newline at end of file diff --git a/src/test/resources/target_code/CNNDataLoader_CifarClassifierNetwork.py b/src/test/resources/target_code/CNNDataLoader_CifarClassifierNetwork.py new file mode 100644 index 00000000..3f6159a1 --- /dev/null +++ b/src/test/resources/target_code/CNNDataLoader_CifarClassifierNetwork.py @@ -0,0 +1,57 @@ +import os +import h5py +import mxnet as mx +import logging +import sys + +class CifarClassifierNetworkDataLoader: + _input_names_ = ['data'] + _output_names_ = ['softmax_label'] + + def __init__(self): + self._data_dir = "data/CifarClassifierNetwork/" + + def load_data(self, batch_size): + train_h5, test_h5 = self.load_h5_files() + + data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) + data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 + + train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], + train_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + test_iter = None + if test_h5 != None: + test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], + test_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + return train_iter, test_iter, data_mean, data_std + + def load_h5_files(self): + train_h5 = None + test_h5 = None + train_path = self._data_dir + "train.h5" + test_path = self._data_dir + "test.h5" + if os.path.isfile(train_path): + train_h5 = h5py.File(train_path, 'r') + if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): + logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + test_iter = None + if os.path.isfile(test_path): + test_h5 = h5py.File(test_path, 'r') + if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): + logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + else: + logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") + return train_h5, test_h5 + else: + logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") + sys.exit(1) \ No newline at end of file diff --git a/src/test/resources/target_code/CNNDataLoader_VGG16.py b/src/test/resources/target_code/CNNDataLoader_VGG16.py new file mode 100644 index 00000000..6a46dba1 --- /dev/null +++ b/src/test/resources/target_code/CNNDataLoader_VGG16.py @@ -0,0 +1,57 @@ +import os +import h5py +import mxnet as mx +import logging +import sys + +class VGG16DataLoader: + _input_names_ = ['data'] + _output_names_ = ['predictions_label'] + + def __init__(self): + self._data_dir = "data/VGG16/" + + def load_data(self, batch_size): + train_h5, test_h5 = self.load_h5_files() + + data_mean = train_h5[self._input_names_[0]][:].mean(axis=0) + data_std = train_h5[self._input_names_[0]][:].std(axis=0) + 1e-5 + + train_iter = mx.io.NDArrayIter(train_h5[self._input_names_[0]], + train_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + test_iter = None + if test_h5 != None: + test_iter = mx.io.NDArrayIter(test_h5[self._input_names_[0]], + test_h5[self._output_names_[0]], + batch_size=batch_size, + data_name=self._input_names_[0], + label_name=self._output_names_[0]) + return train_iter, test_iter, data_mean, data_std + + def load_h5_files(self): + train_h5 = None + test_h5 = None + train_path = self._data_dir + "train.h5" + test_path = self._data_dir + "test.h5" + if os.path.isfile(train_path): + train_h5 = h5py.File(train_path, 'r') + if not (self._input_names_[0] in train_h5 and self._output_names_[0] in train_h5): + logging.error("The HDF5 file '" + os.path.abspath(train_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + test_iter = None + if os.path.isfile(test_path): + test_h5 = h5py.File(test_path, 'r') + if not (self._input_names_[0] in test_h5 and self._output_names_[0] in test_h5): + logging.error("The HDF5 file '" + os.path.abspath(test_path) + "' has to contain the datasets: " + + "'" + self._input_names_[0] + "', '" + self._output_names_[0] + "'") + sys.exit(1) + else: + logging.warning("Couldn't load test set. File '" + os.path.abspath(test_path) + "' does not exist.") + return train_h5, test_h5 + else: + logging.error("Data loading failure. File '" + os.path.abspath(train_path) + "' does not exist.") + sys.exit(1) \ No newline at end of file diff --git a/src/test/resources/target_code/CNNTrainer_emptyConfig.py b/src/test/resources/target_code/CNNTrainer_emptyConfig.py index 60ff25d0..acab71a4 100644 --- a/src/test/resources/target_code/CNNTrainer_emptyConfig.py +++ b/src/test/resources/target_code/CNNTrainer_emptyConfig.py @@ -1,6 +1,8 @@ import logging import mxnet as mx +import supervised_trainer import CNNCreator_emptyConfig +import CNNDataLoader_emptyConfig if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) @@ -8,6 +10,10 @@ if __name__ == "__main__": handler = logging.FileHandler("train.log", "w", encoding=None, delay="true") logger.addHandler(handler) - emptyConfig = CNNCreator_emptyConfig.CNNCreator_emptyConfig() - emptyConfig.train( + emptyConfig_creator = CNNCreator_emptyConfig.CNNCreator_emptyConfig() + emptyConfig_loader = CNNDataLoader_emptyConfig.emptyConfigDataLoader() + emptyConfig_trainer = supervised_trainer.CNNSupervisedTrainer(emptyConfig_loader, + emptyConfig_creator) + + emptyConfig_trainer.train( ) diff --git a/src/test/resources/target_code/CNNTrainer_fullConfig.py b/src/test/resources/target_code/CNNTrainer_fullConfig.py index 2822ae2d..b73c5397 100644 --- a/src/test/resources/target_code/CNNTrainer_fullConfig.py +++ b/src/test/resources/target_code/CNNTrainer_fullConfig.py @@ -1,6 +1,8 @@ import logging import mxnet as mx +import supervised_trainer import CNNCreator_fullConfig +import CNNDataLoader_fullConfig if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) @@ -8,8 +10,12 @@ if __name__ == "__main__": handler = logging.FileHandler("train.log", "w", encoding=None, delay="true") logger.addHandler(handler) - fullConfig = CNNCreator_fullConfig.CNNCreator_fullConfig() - fullConfig.train( + fullConfig_creator = CNNCreator_fullConfig.CNNCreator_fullConfig() + fullConfig_loader = CNNDataLoader_fullConfig.fullConfigDataLoader() + fullConfig_trainer = supervised_trainer.CNNSupervisedTrainer(fullConfig_loader, + fullConfig_creator) + + fullConfig_trainer.train( batch_size=100, num_epoch=5, load_checkpoint=True, diff --git a/src/test/resources/target_code/CNNTrainer_simpleConfig.py b/src/test/resources/target_code/CNNTrainer_simpleConfig.py index bf9f0029..a3b84d28 100644 --- a/src/test/resources/target_code/CNNTrainer_simpleConfig.py +++ b/src/test/resources/target_code/CNNTrainer_simpleConfig.py @@ -1,6 +1,8 @@ import logging import mxnet as mx +import supervised_trainer import CNNCreator_simpleConfig +import CNNDataLoader_simpleConfig if __name__ == "__main__": logging.basicConfig(level=logging.DEBUG) @@ -8,8 +10,12 @@ if __name__ == "__main__": handler = logging.FileHandler("train.log", "w", encoding=None, delay="true") logger.addHandler(handler) - simpleConfig = CNNCreator_simpleConfig.CNNCreator_simpleConfig() - simpleConfig.train( + simpleConfig_creator = CNNCreator_simpleConfig.CNNCreator_simpleConfig() + simpleConfig_loader = CNNDataLoader_simpleConfig.simpleConfigDataLoader() + simpleConfig_trainer = supervised_trainer.CNNSupervisedTrainer(simpleConfig_loader, + simpleConfig_creator) + + simpleConfig_trainer.train( batch_size=100, num_epoch=50, optimizer='adam', diff --git a/src/test/resources/target_code/supervised_trainer.py b/src/test/resources/target_code/supervised_trainer.py new file mode 100644 index 00000000..6a471488 --- /dev/null +++ b/src/test/resources/target_code/supervised_trainer.py @@ -0,0 +1,141 @@ +import mxnet as mx +import logging +import numpy as np +import time +import os +import shutil +from mxnet import gluon, autograd, nd + +class CNNSupervisedTrainer(object): + def __init__(self, data_loader, net_constructor, net=None): + self._data_loader = data_loader + self._net_creator = net_constructor + self._net = net + + def train(self, batch_size=64, + num_epoch=10, + eval_metric='acc', + optimizer='adam', + optimizer_params=(('learning_rate', 0.001),), + load_checkpoint=True, + context='gpu', + checkpoint_period=5, + normalize=True): + if context == 'gpu': + mx_context = mx.gpu() + elif context == 'cpu': + mx_context = mx.cpu() + else: + logging.error("Context argument is '" + context + "'. Only 'cpu' and 'gpu are valid arguments'.") + + if 'weight_decay' in optimizer_params: + optimizer_params['wd'] = optimizer_params['weight_decay'] + del optimizer_params['weight_decay'] + if 'learning_rate_decay' in optimizer_params: + min_learning_rate = 1e-08 + if 'learning_rate_minimum' in optimizer_params: + min_learning_rate = optimizer_params['learning_rate_minimum'] + del optimizer_params['learning_rate_minimum'] + optimizer_params['lr_scheduler'] = mx.lr_scheduler.FactorScheduler( + optimizer_params['step_size'], + factor=optimizer_params['learning_rate_decay'], + stop_factor_lr=min_learning_rate) + del optimizer_params['step_size'] + del optimizer_params['learning_rate_decay'] + + + train_iter, test_iter, data_mean, data_std = self._data_loader.load_data(batch_size) + if self._net is None: + if normalize: + self._net_creator.construct( + context=mx_context, data_mean=nd.array(data_mean), data_std=nd.array(data_std)) + else: + self._net_creator.construct(context=mx_context) + + begin_epoch = 0 + if load_checkpoint: + begin_epoch = self._net_creator.load(mx_context) + else: + if os.path.isdir(self._net_creator._model_dir_): + shutil.rmtree(self._net_creator._model_dir_) + + self._net = self._net_creator.net + + try: + os.makedirs(self._net_creator._model_dir_) + except OSError: + if not os.path.isdir(self._net_creator._model_dir_): + raise + + trainer = mx.gluon.Trainer(self._net.collect_params(), optimizer, optimizer_params) + + if self._net.last_layer == 'softmax': + loss_function = mx.gluon.loss.SoftmaxCrossEntropyLoss() + elif self._net.last_layer == 'sigmoid': + loss_function = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss() + elif self._net.last_layer == 'linear': + loss_function = mx.gluon.loss.L2Loss() + else: # TODO: Change default? + loss_function = mx.gluon.loss.L2Loss() + logging.warning("Invalid last_layer, defaulting to L2 loss") + + speed_period = 50 + tic = None + + for epoch in range(begin_epoch, begin_epoch + num_epoch): + train_iter.reset() + for batch_i, batch in enumerate(train_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + with autograd.record(): + output = self._net(data) + loss = loss_function(output, label) + + loss.backward() + trainer.step(batch_size) + + if tic is None: + tic = time.time() + else: + if batch_i % speed_period == 0: + try: + speed = speed_period * batch_size / (time.time() - tic) + except ZeroDivisionError: + speed = float("inf") + + logging.info("Epoch[%d] Batch[%d] Speed: %.2f samples/sec" % (epoch, batch_i, speed)) + + tic = time.time() + + tic = None + + train_iter.reset() + metric = mx.metric.create(eval_metric) + for batch_i, batch in enumerate(train_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + output = self._net(data) + predictions = mx.nd.argmax(output, axis=1) + metric.update(preds=predictions, labels=label) + train_metric_score = metric.get()[1] + + test_iter.reset() + metric = mx.metric.create(eval_metric) + for batch_i, batch in enumerate(test_iter): + data = batch.data[0].as_in_context(mx_context) + label = batch.label[0].as_in_context(mx_context) + output = self._net(data) + predictions = mx.nd.argmax(output, axis=1) + metric.update(preds=predictions, labels=label) + test_metric_score = metric.get()[1] + + logging.info("Epoch[%d] Train: %f, Test: %f" % (epoch, train_metric_score, test_metric_score)) + + if (epoch - begin_epoch) % checkpoint_period == 0: + self._net.save_parameters(self.parameter_path() + '-' + str(epoch).zfill(4) + '.params') + + self._net.save_parameters(self.parameter_path() + '-' + str(num_epoch + begin_epoch).zfill(4) + '.params') + self._net.export(self.parameter_path() + '_newest', epoch=0) + + def parameter_path(self): + return self._net_creator._model_dir_ + self._net_creator._model_prefix_ \ No newline at end of file -- GitLab