From 16eb0a93eaf9d59d298c4ccfc5cbdb3c1e9f08bb Mon Sep 17 00:00:00 2001 From: Jihoon Lee Date: Mon, 24 May 2021 20:21:25 +0900 Subject: [PATCH] [Fix] Output layer setup correctly There was a bug that output layer is not set correctly because of the timing issue and overlapping checker issue. This patch sets output layer correctly. **Self evaluation:** 1. Build test: [X]Passed [ ]Failed [ ]Skipped 2. Run test: [X]Passed [ ]Failed [ ]Skipped Signed-off-by: Jihoon Lee --- nntrainer/graph/network_graph.cpp | 47 ++++++++++++++++++++++++++------------- nntrainer/graph/network_graph.h | 5 ++++- nntrainer/models/neuralnet.cpp | 10 ++++++--- 3 files changed, 43 insertions(+), 19 deletions(-) diff --git a/nntrainer/graph/network_graph.cpp b/nntrainer/graph/network_graph.cpp index c4cee04..894cb2f 100644 --- a/nntrainer/graph/network_graph.cpp +++ b/nntrainer/graph/network_graph.cpp @@ -229,25 +229,29 @@ int NetworkGraph::realizeActivationType(Layer ¤t) { int NetworkGraph::realizeMultiOutputType(Layer ¤t) { int status = ML_ERROR_NONE; - if (current.getNumOutputs() == 1) + if (current.output_layers.size() == 1) return ML_ERROR_NONE; std::shared_ptr lnode = createLayerNode(OutputLayer::type); std::shared_ptr layer = lnode->getObject(); graph.ensureName(*lnode, current.getName()); - layer->setNumInputs(current.getNumInputs()); layer->input_layers.clear(); layer->input_layers.push_back(current.getName()); + layer->setNumInputs(1); + + layer->output_layers = current.output_layers; layer->setNumOutputs(current.output_layers.size()); - /** output layers for layer obj will be set in setOutputLayers() */ + + current.setNumOutputs(1); + current.output_layers.clear(); + current.output_layers.push_back(layer->getName()); for (unsigned int i = 0; i < current.output_layers.size(); ++i) { updateConnectionName(current.getName(), layer->getName()); } - current.setNumOutputs(layer->getNumInputs()); - + current.setNumOutputs(current.output_layers.size()); graph.addNode(lnode, false); return status; @@ -365,7 +369,7 @@ void NetworkGraph::setOutputLayers() { if (istrequal(layer_i->input_layers[j], layer_idx->getName())) { bool already_exist = false; for (unsigned int k = 0; k < layer_idx->output_layers.size(); ++k) { - if (!istrequal(layer_idx->output_layers[k], layer_i->getName())) { + if (istrequal(layer_idx->output_layers[k], layer_i->getName())) { already_exist = true; break; } @@ -385,9 +389,6 @@ void NetworkGraph::setOutputLayers() { layer_idx->output_layers.push_back("__exit__"); last_layer_count += 1; } else if (layer_idx->getNumOutputs() < layer_idx->output_layers.size()) { - /** this if the multi-output layer */ - if (layer_idx->getType() != OutputLayer::type) - throw std::logic_error("Error: Graph has more edges than expected."); layer_idx->setNumOutputs(layer_idx->output_layers.size()); } else { /** error for any other layer */ @@ -488,11 +489,6 @@ int NetworkGraph::realizeGraph() { NN_RETURN_STATUS(); } - if (l.getType() != OutputLayer::type) { - status = realizeMultiOutputType(l); - NN_RETURN_STATUS(); - } - // Flatten in TimeDistLayer is not supported. if (l.getFlatten() && l.getType() != TimeDistLayer::type) { status = realizeFlattenType(l); @@ -500,7 +496,28 @@ int NetworkGraph::realizeGraph() { } } - setOutputLayers(); + try { + setOutputLayers(); + } catch (std::exception &e) { + ml_loge("setting output layer failed, reason: %s", e.what()); + return ML_ERROR_INVALID_PARAMETER; + } + + num_nodes = graph.size(); + node_list = graph.getNodes(); + + for (unsigned int i = 0; i < num_nodes; ++i) { + Layer &l = *LNODE(node_list[i])->getObject(); + if (l.getType() != OutputLayer::type) { + status = realizeMultiOutputType(l); + NN_RETURN_STATUS(); + } + } + + num_nodes = graph.size(); + node_list = graph.getNodes(); + + /// @todo add check that input_layers <-> output_layers does match. return status; } diff --git a/nntrainer/graph/network_graph.h b/nntrainer/graph/network_graph.h index eac0001..977d08c 100644 --- a/nntrainer/graph/network_graph.h +++ b/nntrainer/graph/network_graph.h @@ -390,7 +390,10 @@ private: void addLayerNode(std::shared_ptr layer); /** - * @brief update name of the the connections + * @brief update input_layers, output_layers node name + * + * @param from update name from @a from + * @param to update name to @a to */ void updateConnectionName(const std::string &from, const std::string &to); diff --git a/nntrainer/models/neuralnet.cpp b/nntrainer/models/neuralnet.cpp index b74d256..3eb4d00 100644 --- a/nntrainer/models/neuralnet.cpp +++ b/nntrainer/models/neuralnet.cpp @@ -217,9 +217,13 @@ sharedConstTensors NeuralNetwork::forwarding(bool training) { sharedConstTensors NeuralNetwork::forwarding(sharedConstTensors input, sharedConstTensors label, bool training) { - if (input[0]->batch() != batch_size || - (!label.empty() && label[0]->batch() != batch_size)) - throw std::logic_error("Error: mismatch in batchsize for data and model."); + + NNTR_THROW_IF(input[0]->batch() != batch_size || + (!label.empty() && label[0]->batch() != batch_size), + std::logic_error) + << "Error: mismatch in batchsize for data and model." + << " input_batch: " << input[0]->batch() + << " label_batch: " << label[0]->batch() << " target_batch: " << batch_size; auto &first_layer = model_graph.getSortedLayerNode(0)->getObject(); auto &last_layer = -- 2.7.4