Aufgrund einer Störung des s3 Storage, könnten in nächster Zeit folgende GitLab Funktionen nicht zur Verfügung stehen: LFS, Container Registry, Job Artifacs, Uploads (Wiki, Bilder, Projekt-Exporte). Wir bitten um Verständnis. Es wird mit Hochdruck an der Behebung des Problems gearbeitet. Weitere Informationen zur Störung des Object Storage finden Sie hier: https://maintenance.itc.rwth-aachen.de/ticket/status/messages/59-object-storage-pilot

Commit 95bfcfa9 authored by Sebastian N.'s avatar Sebastian N.
Browse files

Implemented basic multiple streams

parent bd64e92a
Pipeline #152008 failed with stages
in 3 minutes and 19 seconds
......@@ -7,9 +7,9 @@ public class CNNArch2GluonArchitectureSupportChecker extends ArchitectureSupport
public CNNArch2GluonArchitectureSupportChecker() {}
/*protected boolean checkMultipleStreams(ArchitectureSymbol architecture) {
protected boolean checkMultipleStreams(ArchitectureSymbol architecture) {
return true;
}*/
}
protected boolean checkMultipleInputs(ArchitectureSymbol architecture) {
return true;
......
......@@ -30,7 +30,7 @@ import java.io.Writer;
import java.util.*;
public class CNNArch2GluonTemplateController extends CNNArchTemplateController {
public static final String NET_DEFINITION_MODE_KEY = "definition_mode";
public static final String NET_DEFINITION_MODE_KEY = "mode";
public CNNArch2GluonTemplateController(ArchitectureSymbol architecture,
TemplateConfiguration templateConfiguration) {
......@@ -42,7 +42,7 @@ public class CNNArch2GluonTemplateController extends CNNArchTemplateController {
Map<String, Object> ftlContext = new HashMap<>();
ftlContext.put(TEMPLATE_CONTROLLER_KEY, this);
ftlContext.put(ELEMENT_DATA_KEY, getCurrentElement());
ftlContext.put(NET_DEFINITION_MODE_KEY, netDefinitionMode);
ftlContext.put(NET_DEFINITION_MODE_KEY, netDefinitionMode.toString());
getTemplateConfiguration().processTemplate(ftlContext, templatePath, writer);
}
......@@ -116,4 +116,24 @@ public class CNNArch2GluonTemplateController extends CNNArchTemplateController {
}
include(architectureElement, getWriter(), netDefinitionMode);
}
public List<String> getStreamInputNames(SerialCompositeElementSymbol stream) {
List<String> names = new ArrayList<>();
for (ArchitectureElementSymbol element : stream.getFirstAtomicElements()) {
names.add(getName(element));
}
return names;
}
public List<String> getStreamOutputNames(SerialCompositeElementSymbol stream) {
List<String> names = new ArrayList<>();
for (ArchitectureElementSymbol element : stream.getLastAtomicElements()) {
names.add(getName(element));
}
return names;
}
}
import mxnet as mx
import logging
import os
from CNNNet_${tc.fullArchitectureName} import Net
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
from CNNNet_${tc.fullArchitectureName} import Net_${stream?index}
</#if>
</#list>
class ${tc.fileNameWithoutEnding}:
_model_dir_ = "model/${tc.componentName}/"
_model_prefix_ = "model"
_input_shapes_ = [<#list tc.architecture.inputs as input>(${tc.join(input.definition.type.dimensions, ",")},)<#sep>, </#list>]
def __init__(self):
self.weight_initializer = mx.init.Normal()
self.net = None
def get_input_shapes(self):
return self._input_shapes_
self.networks = {}
def load(self, context):
lastEpoch = 0
param_file = None
try:
os.remove(self._model_dir_ + self._model_prefix_ + "_newest-0000.params")
except OSError:
pass
try:
os.remove(self._model_dir_ + self._model_prefix_ + "_newest-symbol.json")
except OSError:
pass
if os.path.isdir(self._model_dir_):
for file in os.listdir(self._model_dir_):
if ".params" in file and self._model_prefix_ in file:
epochStr = file.replace(".params","").replace(self._model_prefix_ + "-","")
epoch = int(epochStr)
if epoch > lastEpoch:
lastEpoch = epoch
param_file = file
if param_file is None:
return 0
else:
logging.info("Loading checkpoint: " + param_file)
self.net.load_parameters(self._model_dir_ + param_file)
return lastEpoch
earliestLastEpoch = None
for i, network in self.networks.items():
lastEpoch = 0
param_file = None
try:
os.remove(self._model_dir_ + self._model_prefix_ + "_" + str(i) + "_newest-0000.params")
except OSError:
pass
try:
os.remove(self._model_dir_ + self._model_prefix_ + "_" + str(i) + "_newest-symbol.json")
except OSError:
pass
if os.path.isdir(self._model_dir_):
for file in os.listdir(self._model_dir_):
if ".params" in file and self._model_prefix_ + "_" + str(i) in file:
epochStr = file.replace(".params","").replace(self._model_prefix_ + "_" + str(i) + "-","")
epoch = int(epochStr)
if epoch > lastEpoch:
lastEpoch = epoch
param_file = file
if param_file is None:
earliestLastEpoch = 0
else:
logging.info("Loading checkpoint: " + param_file)
network.load_parameters(self._model_dir_ + param_file)
if earliestLastEpoch == None or lastEpoch < earliestLastEpoch:
earliestLastEpoch = lastEpoch
return earliestLastEpoch
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)
self.net.hybridize()
self.net(<#list tc.architecture.inputs as input>mx.nd.zeros((1,) + self._input_shapes_[${input?index}], ctx=context)<#sep>, </#list>)
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
self.networks[${stream?index}] = Net_${stream?index}(data_mean=data_mean, data_std=data_std)
self.networks[${stream?index}].collect_params().initialize(self.weight_initializer, ctx=context)
self.networks[${stream?index}].hybridize()
self.networks[${stream?index}](<#list stream.getFirstAtomicElements() as input>mx.nd.zeros((1, ${tc.join(input.definition.type.dimensions, ",")},), ctx=context)<#sep>, </#list>)
</#if>
</#list>
if not os.path.exists(self._model_dir_):
os.makedirs(self._model_dir_)
self.net.export(self._model_dir_ + self._model_prefix_, epoch=0)
for i, network in self.networks.items():
network.export(self._model_dir_ + self._model_prefix_ + "_" + str(i), epoch=0)
......@@ -78,18 +78,22 @@ class NoNormalization(gluon.HybridBlock):
return x
class Net(gluon.HybridBlock):
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
class Net_${stream?index}(gluon.HybridBlock):
def __init__(self, data_mean=None, data_std=None, **kwargs):
super(Net, self).__init__(**kwargs)
super(Net_${stream?index}, self).__init__(**kwargs)
self.last_layers = {}
with self.name_scope():
${tc.include(tc.architecture.streams[0], "ARCHITECTURE_DEFINITION")}
${tc.include(stream, "ARCHITECTURE_DEFINITION")}
def hybrid_forward(self, F, ${tc.join(tc.architectureInputs, ", ")}):
<#if tc.architectureOutputs?size gt 1>
def hybrid_forward(self, F, ${tc.join(tc.getStreamInputNames(stream), ", ")}):
outputs = []
</#if>
${tc.include(tc.architecture.streams[0], "FORWARD_FUNCTION")}
<#if tc.architectureOutputs?size gt 1>
${tc.include(stream, "FORWARD_FUNCTION")}
<#if tc.getStreamOutputNames(stream)?size gt 1>
return tuple(outputs)
</#if>
<#else>
return outputs[0]
</#if>
</#if>
</#list>
\ No newline at end of file
......@@ -9,34 +9,36 @@
#include <CNNBufferFile.h>
class ${tc.fileNameWithoutEnding}{
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
class ${tc.fileNameWithoutEnding}_${stream?index}{
public:
const std::string json_file = "model/${tc.componentName}/model_newest-symbol.json";
const std::string param_file = "model/${tc.componentName}/model_newest-0000.params";
const std::string json_file = "model/${tc.componentName}/model_${stream?index}_newest-symbol.json";
const std::string param_file = "model/${tc.componentName}/model_${stream?index}_newest-0000.params";
const std::vector<std::string> input_keys = {
<#if (tc.architectureInputs?size == 1)>
<#if (tc.getStreamInputNames(stream)?size == 1)>
"data"
<#else>
<#list tc.architectureInputs as inputName>"data${inputName?index}"<#sep>, </#list>
<#list tc.getStreamInputNames(stream) as inputName>"data${inputName?index}"<#sep>, </#list>
</#if>
};
const std::vector<std::vector<mx_uint>> input_shapes = {<#list tc.architecture.inputs as input>{1, ${tc.join(input.definition.type.dimensions, ", ")}}<#sep>, </#list>};
const std::vector<std::vector<mx_uint>> input_shapes = {<#list stream.getFirstAtomicElements() as input>{1, ${tc.join(input.definition.type.dimensions, ", ")}}<#sep>, </#list>};
const bool use_gpu = false;
PredictorHandle handle;
explicit ${tc.fileNameWithoutEnding}(){
explicit ${tc.fileNameWithoutEnding}_${stream?index}(){
init(json_file, param_file, input_keys, input_shapes, use_gpu);
}
~${tc.fileNameWithoutEnding}(){
~${tc.fileNameWithoutEnding}_${stream?index}(){
if(handle) MXPredFree(handle);
}
void predict(${tc.join(tc.architectureInputs, ", ", "const std::vector<float> &", "")},
${tc.join(tc.architectureOutputs, ", ", "std::vector<float> &", "")}){
<#list tc.architectureInputs as inputName>
<#if (tc.architectureInputs?size == 1)>
void predict(${tc.join(tc.getStreamInputNames(stream), ", ", "const std::vector<float> &", "")},
${tc.join(tc.getStreamOutputNames(stream), ", ", "std::vector<float> &", "")}){
<#list tc.getStreamInputNames(stream) as inputName>
<#if (tc.getStreamInputNames(stream)?size == 1)>
MXPredSetInput(handle, "data", ${inputName}.data(), static_cast<mx_uint>(${inputName}.size()));
<#else>
MXPredSetInput(handle, "data${inputName?index}", ${inputName}.data(), static_cast<mx_uint>(${inputName}.size()));
......@@ -50,7 +52,7 @@ public:
mx_uint shape_len;
size_t size;
<#list tc.architectureOutputs as outputName>
<#list tc.getStreamOutputNames(stream) as outputName>
output_index = ${outputName?index?c};
MXPredGetOutputShape(handle, output_index, &shape, &shape_len);
size = 1;
......@@ -115,5 +117,7 @@ public:
assert(handle);
}
};
</#if>
</#list>
#endif // ${tc.fileNameWithoutEnding?upper_case}
......@@ -7,10 +7,10 @@ import shutil
from mxnet import gluon, autograd, nd
class ${tc.fileNameWithoutEnding}:
def __init__(self, data_loader, net_constructor, net=None):
def __init__(self, data_loader, net_constructor):
self._data_loader = data_loader
self._net_creator = net_constructor
self._net = net
self._networks = {}
def train(self, batch_size=64,
num_epoch=10,
......@@ -45,12 +45,11 @@ class ${tc.fileNameWithoutEnding}:
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=data_mean, data_std=data_std)
else:
self._net_creator.construct(context=mx_context)
if normalize:
self._net_creator.construct(context=mx_context, data_mean=data_mean, data_std=data_std)
else:
self._net_creator.construct(context=mx_context)
begin_epoch = 0
if load_checkpoint:
......@@ -59,7 +58,7 @@ class ${tc.fileNameWithoutEnding}:
if os.path.isdir(self._net_creator._model_dir_):
shutil.rmtree(self._net_creator._model_dir_)
self._net = self._net_creator.net
self._networks = self._net_creator.networks
try:
os.makedirs(self._net_creator._model_dir_)
......@@ -67,20 +66,21 @@ class ${tc.fileNameWithoutEnding}:
if not os.path.isdir(self._net_creator._model_dir_):
raise
trainer = mx.gluon.Trainer(self._net.collect_params(), optimizer, optimizer_params)
trainers = [mx.gluon.Trainer(network.collect_params(), optimizer, optimizer_params) for network in self._networks.values()]
loss_functions = {}
for output_name, last_layer in self._net.last_layers.items():
if last_layer == 'softmax':
loss_functions[output_name] = mx.gluon.loss.SoftmaxCrossEntropyLoss()
elif last_layer == 'sigmoid':
loss_functions[output_name] = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss()
elif last_layer == 'linear':
loss_functions[output_name] = mx.gluon.loss.L2Loss()
else:
loss_functions[output_name] = mx.gluon.loss.L2Loss()
logging.warning("Invalid last layer, defaulting to L2 loss")
for network in self._networks.values():
for output_name, last_layer in network.last_layers.items():
if last_layer == 'softmax':
loss_functions[output_name] = mx.gluon.loss.SoftmaxCrossEntropyLoss()
elif last_layer == 'sigmoid':
loss_functions[output_name] = mx.gluon.loss.SigmoidBinaryCrossEntropyLoss()
elif last_layer == 'linear':
loss_functions[output_name] = mx.gluon.loss.L2Loss()
else:
loss_functions[output_name] = mx.gluon.loss.L2Loss()
logging.warning("Invalid last layer, defaulting to L2 loss")
speed_period = 50
tic = None
......@@ -96,12 +96,20 @@ class ${tc.fileNameWithoutEnding}:
</#list>
with autograd.record():
${tc.join(tc.architectureOutputs, ", ", "", "_output")} = self._net(${tc.join(tc.architectureInputs, ", ", "", "_data")})
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
${tc.join(tc.getStreamOutputNames(stream), ", ", "", "_output")} = self._networks[${stream?index}](${tc.join(tc.getStreamInputNames(stream), ", ", "", "_data")})
<#else>
# TODO: Implement non network streams
</#if>
</#list>
loss = <#list tc.architectureOutputs as output_name>loss_functions['${output_name}'](${output_name}_output, ${output_name}_label)<#sep> + </#list>
loss.backward()
trainer.step(batch_size)
for trainer in trainers:
trainer.step(batch_size)
if tic is None:
tic = time.time()
......@@ -129,7 +137,13 @@ class ${tc.fileNameWithoutEnding}:
<#list tc.architectureOutputs as output_name>batch.label[${output_name?index}].as_in_context(mx_context)<#sep>, </#list>
]
${tc.join(tc.architectureOutputs, ", ", "", "_output")} = self._net(${tc.join(tc.architectureInputs, ", ", "", "_data")})
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
${tc.join(tc.getStreamOutputNames(stream), ", ", "", "_output")} = self._networks[${stream?index}](${tc.join(tc.getStreamInputNames(stream), ", ", "", "_data")})
<#else>
# TODO: Implement non network streams
</#if>
</#list>
predictions = [
<#list tc.architectureOutputs as output_name>mx.nd.argmax(${output_name}_output, axis=1)<#sep>, </#list>
......@@ -149,8 +163,13 @@ class ${tc.fileNameWithoutEnding}:
<#list tc.architectureOutputs as output_name>batch.label[${output_name?index}].as_in_context(mx_context)<#sep>, </#list>
]
${tc.join(tc.architectureOutputs, ", ", "", "_output")} = self._net(${tc.join(tc.architectureInputs, ", ", "", "_data")})
<#list tc.architecture.streams as stream>
<#if stream.isNetwork()>
${tc.join(tc.getStreamOutputNames(stream), ", ", "", "_output")} = self._networks[${stream?index}](${tc.join(tc.getStreamInputNames(stream), ", ", "", "_data")})
<#else>
# TODO: Implement non network streams
</#if>
</#list>
predictions = [
<#list tc.architectureOutputs as output_name>mx.nd.argmax(${output_name}_output, axis=1)<#sep>, </#list>
]
......@@ -161,10 +180,12 @@ class ${tc.fileNameWithoutEnding}:
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')
for i, network in self._networks.items():
network.save_parameters(self.parameter_path(i) + '-' + 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)
for i, network in self._networks.items():
network.save_parameters(self.parameter_path(i) + '-' + str(num_epoch + begin_epoch).zfill(4) + '.params')
network.export(self.parameter_path(i) + '_newest', epoch=0)
def parameter_path(self):
return self._net_creator._model_dir_ + self._net_creator._model_prefix_
\ No newline at end of file
def parameter_path(self, index):
return self._net_creator._model_dir_ + self._net_creator._model_prefix_ + '_' + str(index)
\ No newline at end of file
<#-- TODO: May put this in an extra HybridBlock -->
<#assign mode = definition_mode.toString()>
<#if mode == "FORWARD_FUNCTION">
${element.name} = ${tc.join(element.inputs, " + ")}
</#if>
\ No newline at end of file
<#assign mode = definition_mode.toString()>
<#assign input = element.inputs[0]>
<#-- TODO: Find solution for the CNNArch fix_gamma parameter of BatchNorm. Gluon does not provide this parameter-->
<#if mode == "ARCHITECTURE_DEFINITION">
......
<#assign mode = definition_mode.toString()>
<#if mode == "ARCHITECTURE_DEFINITION">
self.${element.name} = Concatenate(dim=1)
<#include "OutputShape.ftl">
......
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#if mode == "ARCHITECTURE_DEFINITION">
<#if element.padding??>
self.${element.name}padding = Padding(padding=(${tc.join(element.padding, ",")}))
......
<#assign mode = definition_mode.toString()>
<#assign rate = element.p?c>
<#assign input = element.inputs[0]>
<#if mode == "ARCHITECTURE_DEFINITION">
......
<#assign mode = definition_mode.toString()>
<#assign input = element.inputs[0]>
<#if mode == "ARCHITECTURE_DEFINITION">
self.${element.name} = gluon.nn.Flatten()
......
......@@ -2,7 +2,6 @@
<#assign input = element.inputs[0]>
<#assign units = element.units?c>
<#assign use_bias = element.noBias?string("False","True")>
<#assign mode = definition_mode.toString()>
<#if mode == "ARCHITECTURE_DEFINITION">
<#if flatten>
self.${element.name}flatten = gluon.nn.Flatten()
......
<#assign mode = definition_mode.toString()>
<#if mode == "FORWARD_FUNCTION">
${element.name} = ${element.inputs[element.index]}
</#if>
\ No newline at end of file
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#assign poolType = element.poolType>
<#if poolType == "avg">
<#assign poolFunctionType = "Avg">
......
<#assign mode = definition_mode.toString()>
<#if mode == "ARCHITECTURE_DEFINITION">
if data_mean:
assert(data_std)
......
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#if mode == "FORWARD_FUNCTION">
${element.name} = F.LRN(data=${input},
alpha=${element.alpha?c},
......
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#assign size = element.size>
<#if mode == "ARCHITECTURE_DEFINITION">
self.${element.name} = OneHot(size=${size})
......
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#if mode == "ARCHITECTURE_DEFINITION">
<#if element.softmaxOutput>
self.last_layers['${element.name}'] = 'softmax'
......@@ -12,9 +11,5 @@
</#if>
</#if>
<#if mode == "FORWARD_FUNCTION">
<#if tc.architectureOutputs?size gt 1>
outputs.append(${input})
<#else>
return ${input}
</#if>
</#if>
<#assign input = element.inputs[0]>
<#assign mode = definition_mode.toString()>
<#assign poolType = element.poolType>
<#assign poolSize = "(" + tc.join(element.kernel, ",") + ")">
<#assign strides = "(" + tc.join(element.stride, ",") + ")">
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment