From: hyeonseok lee Date: Wed, 26 Oct 2022 06:32:59 +0000 (+0900) Subject: [split layer] make a unittest to test split input dimension by split number X-Git-Tag: accepted/tizen/unified/20230425.130129~119 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=f5546858a688742ec6763181ba7b8ffc6e933758;p=platform%2Fcore%2Fml%2Fnntrainer.git [split layer] make a unittest to test split input dimension by split number - Make a unittest to test split input dimension by split number - Conv2d layer is added to make model has a weight Signed-off-by: hyeonseok lee --- diff --git a/nntrainer/layers/common_properties.h b/nntrainer/layers/common_properties.h index a5a9c46..f99fd96 100644 --- a/nntrainer/layers/common_properties.h +++ b/nntrainer/layers/common_properties.h @@ -250,8 +250,8 @@ public: }; /** - * @brief split number property, split number is used to split input dimension - * in split layer + * @brief split number property, split number indicates how many numbers of outs + * are generated by spliting the input dimension * */ class SplitNumber : public PositiveIntegerProperty { diff --git a/nntrainer/layers/split_layer.cpp b/nntrainer/layers/split_layer.cpp index 4e55d81..2b15f07 100644 --- a/nntrainer/layers/split_layer.cpp +++ b/nntrainer/layers/split_layer.cpp @@ -34,20 +34,22 @@ void SplitLayer::finalize(InitLayerContext &context) { unsigned int split_dimension = std::get(split_props); + const TensorDim &in_dim = context.getInputDimensions()[0]; + if (std::get(split_props).empty()) { std::get(split_props) - .set(context.getNumRequestedOutputs()); + .set(in_dim.getTensorDim(split_dimension)); } unsigned int split_number = std::get(split_props); /** * The split is only done along the split_dimension dimension. + * (Assumes input data is continous) * For example, consider input dimension [b,c,h,w], split_number = n - * 1. axis = 1, output_dim = [b,n,h,w], num_outputs = c//n - * 2. axis = 2, output_dim = [b,c,n,w], num_outputs = h//n - * 3. axis = 3, output_dim = [b,c,h,n], num_outputs = w//n + * 1. axis = 1, output_dim = [b,c//n,h,w], num_outputs = n + * 2. axis = 2, output_dim = [b,c,h//n,w], num_outputs = n + * 3. axis = 3, output_dim = [b,c,h,w//n], num_outputs = n */ - const TensorDim &in_dim = context.getInputDimensions()[0]; NNTR_THROW_IF(split_number != context.getNumRequestedOutputs(), std::invalid_argument) << "Given split number does not match with number of outputs"; diff --git a/packaging/unittest_models_multiout.tar.gz b/packaging/unittest_models_multiout.tar.gz index 689f8db..ce44df3 100644 Binary files a/packaging/unittest_models_multiout.tar.gz and b/packaging/unittest_models_multiout.tar.gz differ diff --git a/test/input_gen/genModelsMultiout_v2.py b/test/input_gen/genModelsMultiout_v2.py index 6fff417..20a4996 100644 --- a/test/input_gen/genModelsMultiout_v2.py +++ b/test/input_gen/genModelsMultiout_v2.py @@ -11,6 +11,24 @@ from recorder_v2 import record_v2, inspect_file import torch +class Split(torch.nn.Module): + def __init__(self, axis, split_number, channel): + super().__init__() + self.axis = axis + self.split_number = split_number + self.conv = torch.nn.Conv2d(channel, channel, 1) + self.loss = torch.nn.MSELoss() + + def forward(self, inputs, labels): + outs = self.conv(inputs[0]) + split_size = outs.size(self.axis) // self.split_number + *outs, = torch.split(outs, split_size, self.axis) + out = torch.clone(outs[0]) + for i in range(1, len(outs)): + out += outs[i] + + loss = self.loss(out, labels[0]) + return out, loss class SplitAndJoin(torch.nn.Module): def __init__(self): @@ -93,6 +111,30 @@ class OneToMany(torch.nn.Module): if __name__ == "__main__": record_v2( + Split(3, 5, 3), + iteration=2, + input_dims=[(2, 3, 4, 5)], + label_dims=[(2, 3, 4, 1)], + name="split_axis3_split_number5" + ) + + record_v2( + Split(2, 4, 3), + iteration=2, + input_dims=[(2, 3, 4, 5)], + label_dims=[(2, 3, 1, 5)], + name="split_axis2_split_number4" + ) + + record_v2( + Split(2, 2, 3), + iteration=2, + input_dims=[(2, 3, 4, 5)], + label_dims=[(2, 3, 2, 5)], + name="split_axis2_split_number2" + ) + + record_v2( SplitAndJoin(), iteration=2, input_dims=[(5, 3)], diff --git a/test/unittest/models/unittest_models_multiout.cpp b/test/unittest/models/unittest_models_multiout.cpp index 2f330b7..e262b7c 100644 --- a/test/unittest/models/unittest_models_multiout.cpp +++ b/test/unittest/models/unittest_models_multiout.cpp @@ -22,6 +22,65 @@ using namespace nntrainer; +static std::unique_ptr split_axis3_split_number5() { + std::unique_ptr nn(new NeuralNetwork()); + nn->setProperty({"batch_size=2"}); + + auto graph = makeGraph({ + {"conv2d", + {"name=conv", "input_shape=3:4:5", "filters=3", "kernel_size=1,1"}}, + {"split", {"name=split", "input_layers=conv", "axis=3", "split_number=5"}}, + {"addition", + {"name=add", "input_layers=split(0),split(1),split(2),split(3),split(4)"}}, + {"mse", {"name=loss", "input_layers=add"}}, + }); + for (auto &node : graph) { + nn->addLayer(node); + } + + nn->setOptimizer(ml::train::createOptimizer("sgd", {"learning_rate = 0.1"})); + return nn; +} + +static std::unique_ptr split_axis2_split_number4() { + std::unique_ptr nn(new NeuralNetwork()); + nn->setProperty({"batch_size=2"}); + + auto graph = makeGraph({ + {"conv2d", + {"name=conv", "input_shape=3:4:5", "filters=3", "kernel_size=1,1"}}, + {"split", {"name=split", "input_layers=conv", "axis=2", "split_number=4"}}, + {"addition", + {"name=add", "input_layers=split(0),split(1),split(2),split(3)"}}, + {"mse", {"name=loss", "input_layers=add"}}, + }); + for (auto &node : graph) { + nn->addLayer(node); + } + + nn->setOptimizer(ml::train::createOptimizer("sgd", {"learning_rate = 0.1"})); + return nn; +} + +static std::unique_ptr split_axis2_split_number2() { + std::unique_ptr nn(new NeuralNetwork()); + nn->setProperty({"batch_size=2"}); + + auto graph = makeGraph({ + {"conv2d", + {"name=conv", "input_shape=3:4:5", "filters=3", "kernel_size=1,1"}}, + {"split", {"name=split", "input_layers=conv", "axis=2", "split_number=2"}}, + {"addition", {"name=add", "input_layers=split(0),split(1)"}}, + {"mse", {"name=loss", "input_layers=add"}}, + }); + for (auto &node : graph) { + nn->addLayer(node); + } + + nn->setOptimizer(ml::train::createOptimizer("sgd", {"learning_rate = 0.1"})); + return nn; +} + /// A has two output tensor a1, a2 and B, C takes it /// A /// (a0, a1) @@ -176,6 +235,12 @@ static std::unique_ptr split_and_join_dangle() { GTEST_PARAMETER_TEST( multiInoutModels, nntrainerModelTest, ::testing::ValuesIn({ + mkModelTc_V2(split_axis3_split_number5, "split_axis3_split_number5", + ModelTestOption::ALL_V2), + mkModelTc_V2(split_axis2_split_number4, "split_axis2_split_number4", + ModelTestOption::ALL_V2), + mkModelTc_V2(split_axis2_split_number2, "split_axis2_split_number2", + ModelTestOption::ALL_V2), mkModelTc_V2(split_and_join, "split_and_join", ModelTestOption::ALL_V2), mkModelTc_V2(one_to_one, "one_to_one", ModelTestOption::ALL_V2), mkModelTc_V2(one_to_one_reversed, "one_to_one__reversed",