From 15c81bdbe57bebf40a6948d0d8b31da28def9d3a Mon Sep 17 00:00:00 2001 From: Jihoon Lee Date: Mon, 5 Apr 2021 21:12:35 +0900 Subject: [PATCH] [IniInterpreter] Add test setup This patch add a test setup to test interpreter. **Self evaluation:** 1. Build test: [X]Passed [ ]Failed [ ]Skipped 2. Run test: [X]Passed [ ]Failed [ ]Skipped Signed-off-by: Jihoon Lee --- nntrainer/compiler/ini_interpreter.cpp | 10 +- nntrainer/graph/network_graph.cpp | 4 + test/test_models/models/simple_fc.ini | 7 ++ test/test_models/models/simple_fc_backbone.ini | 3 + test/unittest/compiler/unittest_interpreter.cpp | 119 ++++++++++++++++++++++++ 5 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 test/test_models/models/simple_fc.ini create mode 100644 test/test_models/models/simple_fc_backbone.ini diff --git a/nntrainer/compiler/ini_interpreter.cpp b/nntrainer/compiler/ini_interpreter.cpp index eb4074f..dfa6076 100644 --- a/nntrainer/compiler/ini_interpreter.cpp +++ b/nntrainer/compiler/ini_interpreter.cpp @@ -117,7 +117,7 @@ section2layer(dictionary *ini, const std::string &sec_name, const std::string &layer_type = iniparser_getstring(ini, (sec_name + ":Type").c_str(), UNKNOWN_STR); NNTR_THROW_IF(layer_type == UNKNOWN_STR, std::invalid_argument) - << FUNC_TAG << "section name is invalid, section name: " << sec_name; + << FUNC_TAG << "section type is invalid for section name: " << sec_name; auto properties = section2properties(ini, sec_name); std::shared_ptr layer_ = @@ -157,8 +157,6 @@ section2layer(dictionary *ini, const std::string &sec_name, ac.createObject(type, properties); auto layer = std::static_pointer_cast(layer_); - int status = layer->setName(sec_name); - throw_status(status); return layer; } @@ -228,7 +226,7 @@ getMergeableGraph(std::shared_ptr graph, /** FIXME :the layers is not the actual model_graph. It is just the vector of * layers generated by Model Loader. so graph[0] is still valid. Also we need - * to consider that the first layer of ini might be th first of layers. Need + * to consider that the first layer of ini might be the first of layers. Need * to change by compiling the backbone before using here. */ std::string input_shape = iniparser_getstring(ini, (sec_name + ":Input_Shape").c_str(), ""); @@ -238,7 +236,7 @@ getMergeableGraph(std::shared_ptr graph, std::string input_layers = iniparser_getstring(ini, (sec_name + ":Input_Layers").c_str(), ""); - if (!input_layers.empty() && g.size() != 0) { + if (!input_layers.empty()) { g[0]->setProperty(Layer::PropertyType::input_layers, input_layers); } @@ -257,7 +255,7 @@ IniGraphInterpreter::deserialize(const std::string &in) { << FUNC_TAG << "given in file is empty"; NNTR_THROW_IF(!isFileExist(in), std::invalid_argument) - << FUNC_TAG << "given ini file does not exist"; + << FUNC_TAG << "given ini file does not exist, file_path: " << in; dictionary *ini = iniparser_load(in.c_str()); NNTR_THROW_IF(!ini, std::runtime_error) << "loading ini failed"; diff --git a/nntrainer/graph/network_graph.cpp b/nntrainer/graph/network_graph.cpp index 3ae235b..012a8d4 100644 --- a/nntrainer/graph/network_graph.cpp +++ b/nntrainer/graph/network_graph.cpp @@ -636,6 +636,10 @@ std::vector NetworkGraph::getOutputDimension() const { std::vector> NetworkGraph::getUnsortedLayers(const std::string &input_layer, const std::string &output_layer) const { + /// @FIXME: this won't work if input, output layers are not in order + /// Further, this function must be removed. There should be rather + /// getAllNames and getLayerByName instead of getUnsortedLayers. + /** count layers after output layer */ unsigned int num_layers_remove_end = 0; if (!output_layer.empty()) { diff --git a/test/test_models/models/simple_fc.ini b/test/test_models/models/simple_fc.ini new file mode 100644 index 0000000..28c9ca4 --- /dev/null +++ b/test/test_models/models/simple_fc.ini @@ -0,0 +1,7 @@ +[fc0] +type=fully_connected +input_shape = 1:1:100 +unit=1 + +[flat] +type=flatten diff --git a/test/test_models/models/simple_fc_backbone.ini b/test/test_models/models/simple_fc_backbone.ini new file mode 100644 index 0000000..272bcba --- /dev/null +++ b/test/test_models/models/simple_fc_backbone.ini @@ -0,0 +1,3 @@ +[] +backbone="simple_fc.ini" +input_shape=1:1:100 diff --git a/test/unittest/compiler/unittest_interpreter.cpp b/test/unittest/compiler/unittest_interpreter.cpp index d10e9b3..196f7e4 100644 --- a/test/unittest/compiler/unittest_interpreter.cpp +++ b/test/unittest/compiler/unittest_interpreter.cpp @@ -10,6 +10,125 @@ * @bug No known bugs except for NYI items */ +#include #include +#include +#include +#include #include +#include + +#include + +using LayerReprentation = std::pair>; + +auto &ac = nntrainer::AppContext::Global(); + +static std::shared_ptr +makeGraph(const std::vector &layer_reps) { + auto graph = std::make_shared(); + + for (const auto &layer_representation : layer_reps) { + std::shared_ptr layer = ac.createObject( + layer_representation.first, layer_representation.second); + graph->addLayer(std::static_pointer_cast(layer)); + } + + return graph; +} + +const std::string pathResolver(const std::string &path) { + return getResPath(path, {"test", "test_models", "models"}); +} + +auto ini_interpreter = + std::make_shared(ac, pathResolver); + +/** + * @brief nntrainer Interpreter Test setup + * + * @note Proposing an evolutional path of current test + * 1. A reference graph vs given paramter + * 2. A reference graph vs list of models + * 3. A reference graph vs (pick two models) a -> b -> a graph, b -> a -> b + * graph + */ +class nntrainerInterpreterTest + : public ::testing::TestWithParam< + std::tuple, const char *, + std::shared_ptr>> { + +protected: + virtual void SetUp() { + auto params = GetParam(); + + reference = std::get<0>(params); + file_path = pathResolver(std::get<1>(params)); + interpreter = std::move(std::get<2>(params)); + } + + std::shared_ptr reference; + std::shared_ptr interpreter; + std::string file_path; +}; + +/** + * @brief Check two compiled graph is equal + * @note later this will be more complicated (getting N graph and compare each + * other) + * + */ +TEST_P(nntrainerInterpreterTest, graphEqual) { + std::cerr << "testing " << file_path << '\n'; + + int status = reference->compile(nntrainer::LossType::LOSS_NONE); + EXPECT_EQ(status, ML_ERROR_NONE); + auto g = interpreter->deserialize(file_path); + + /// @todo: change this to something like graph::finalize + status = g->compile(nntrainer::LossType::LOSS_NONE); + EXPECT_EQ(status, ML_ERROR_NONE); + + /// @todo: make a graph equal + /// 1. having same number of nodes + /// 2. layer name is identical (this is too strict though) + /// 3. attributes of layer is identical + // EXPECT_EQ(*graph, *interpreter->deserialize(file_path)); + + auto layers = g->getLayers(); + auto ref_layers = reference->getLayers(); + EXPECT_EQ(layers.size(), ref_layers.size()); + + if (layers.size() == ref_layers.size()) { + for (auto &layer : layers) { + std::shared_ptr ref_layer; + EXPECT_NO_THROW(ref_layer = reference->getLayer(layer->getName())); + + /// @todo: layer->getProperties() and do check on each properties + } + } +} + +auto fc0 = LayerReprentation("fully_connected", + {"name=fc0", "unit=1", "input_shape=1:1:100"}); + +auto flatten = LayerReprentation("flatten", {"name=flat"}); + +/** + * @brief make ini test case from given parameter + */ +static std::tuple, const char *, + std::shared_ptr> +mkTc(std::shared_ptr graph, const char *file, + std::shared_ptr interpreter) { + return std::make_tuple(graph, file, interpreter); +} + +// clang-format off +INSTANTIATE_TEST_CASE_P(nntrainerAutoInterpreterTest, nntrainerInterpreterTest, + ::testing::Values( + mkTc(makeGraph({fc0, flatten}), "simple_fc.ini", ini_interpreter), + mkTc(makeGraph({fc0, flatten}), "simple_fc_backbone.ini", ini_interpreter) +)); +// clang-format on -- 2.7.4