[ LSTM ] LSTM Unit Test Cases
authorjijoong.moon <jijoong.moon@samsung.com>
Tue, 18 May 2021 01:24:54 +0000 (10:24 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Tue, 8 Jun 2021 07:41:32 +0000 (16:41 +0900)
This PR includes,
 . LSTM Unittest Case
 . python code in genModels

Resolves:

**Self evaluation:**
1. Build test:  [X]Passed [ ]Failed [ ]Skipped
2. Run test:  [X]Passed [ ]Failed [ ]Skipped

Signed-off-by: jijoong.moon <jijoong.moon@samsung.com>
test/input_gen/genModelTests.py
test/input_gen/recorder.py
test/unittest/unittest_nntrainer_models.cpp

index af03eea..012c405 100644 (file)
@@ -327,3 +327,19 @@ if __name__ == "__main__":
         debug=["name", "summary"],
     )
 
+    lstm_layer_tc = lambda lstm_layer: partial(
+        record,
+        model=[
+            K.Input(batch_shape=(1, 2, 1)),
+            lstm_layer,
+            K.layers.Dense(1)
+        ],
+        optimizer=opt.SGD(learning_rate=0.1),
+        iteration=1,
+        input_shape=(1,2,1),
+        label_shape=(1,1),
+        is_onehot=False,
+        loss_fn_str="mse"
+    )
+    lstm = K.layers.LSTM(2)
+    lstm_layer_tc(lstm)(file_name="lstm_basic.info", debug=["summary", "initial_weights", "dx", "output", "layer_name", "label"],)
index ad7a8f3..16491c8 100644 (file)
@@ -114,12 +114,15 @@ def _debug_print(
 ##
 # @brief generate data using uniform data from a function and save to the file.
 # @note one-hot label is supported for now, this could be extended if needed.
-def prepare_data(model, input_shape, label_shape, writer_fn, **kwargs):
+def prepare_data(model, input_shape, label_shape, writer_fn, is_onehot, **kwargs):
     initial_input = _rand_like(input_shape)
-    label = tf.one_hot(
-        indices=np.random.randint(0, label_shape[1] - 1, label_shape[0]),
-        depth=label_shape[1],
-    )
+    if is_onehot:
+        label = tf.one_hot(
+            indices=np.random.randint(0, label_shape[1] - 1, label_shape[0]),
+            depth=label_shape[1],
+        )
+    else:
+        label=_rand_like(label_shape)
 
     initial_weights = []
     for layer in iter_model(model):
@@ -248,7 +251,7 @@ value_only_formatter = lambda key, value: value
 # @param inputs keras inputs to build a model
 # @param outputs keras outputs to build a model
 def generate_recordable_model(
-    loss_fn_str, model=None, inputs=None, outputs=None, **kwargs
+        loss_fn_str, model=None, inputs=None, outputs=None, is_onehot=False, **kwargs
 ):
     if isinstance(model, list):
         model = [attach_trans_layer(layer) for layer in model]
@@ -348,21 +351,21 @@ def record(
     model=None,
     inputs=None,
     outputs=None,
+    is_onehot=True,
     **kwargs
 ):
     if os.path.isfile(file_name):
         print("Warning: the file %s is being truncated and overwritten" % file_name)
 
     loss_fn = _get_loss_fn(loss_fn_str)
-    model = generate_recordable_model(loss_fn_str, model, inputs, outputs, **kwargs)
+    model = generate_recordable_model(loss_fn_str, model, inputs, outputs, is_onehot, **kwargs)
 
     with open(file_name, "wb") as f:
         write = _get_writer(f)
 
         initial_input, label = prepare_data(
-            model, input_shape, label_shape, write, **kwargs
+            model, input_shape, label_shape, write, is_onehot, **kwargs
         )
-
         for _ in range(iteration):
             _debug_print(
                 iteration="\033[1;33m[%d/%d]\033[0m" % (_ + 1, iteration),
index 660aff0..e9cbe42 100644 (file)
@@ -607,6 +607,7 @@ static nntrainer::IniSection nn_base("model", "type = NeuralNetwork");
 static std::string input_base = "type = input";
 static std::string fc_base = "type = Fully_connected";
 static std::string conv_base = "type = conv2d | stride = 1,1 | padding = 0,0";
+static std::string lstm_base = "type = lstm";
 static std::string pooling_base = "type = pooling2d | padding = 0,0";
 static std::string preprocess_flip_base = "type = preprocess_flip";
 static std::string preprocess_translate_base = "type = preprocess_translate";
@@ -1067,6 +1068,18 @@ INI addition_resnet_like_validate(
   }
 );
 
+INI lstm_basic(
+  "lstm_basic",
+  {
+    nn_base + "loss=mse | batch_size=1",
+    sgd_base + "learning_rate = 0.1",
+    I("input") + input_base + "input_shape=1:2:1",
+    I("lstm") + lstm_base +
+      "unit = 2" + "input_layers=input",
+    I("outputlayer") + fc_base + "unit = 1" + "input_layers=lstm"
+  }
+);
+
 INSTANTIATE_TEST_CASE_P(
   nntrainerModelAutoTests, nntrainerModelTest, ::testing::Values(
     mkModelTc(fc_sigmoid_mse, "3:1:1:10", 10),
@@ -1105,11 +1118,13 @@ INSTANTIATE_TEST_CASE_P(
 
     /**< Addition test */
     mkModelTc(addition_resnet_like_validate, "3:1:1:10", 10)
+    mkModelTc(preprocess_flip_validate, "3:1:1:10", 10)
 
     /// #1192 time distribution inference bug
     // mkModelTc(fc_softmax_mse_distribute_validate, "3:1:5:3", 1),
     // mkModelTc(fc_softmax_cross_distribute_validate, "3:1:5:3", 1),
     // mkModelTc(fc_sigmoid_cross_distribute_validate, "3:1:5:3", 1)
+    mkModelTc(lstm_basic, "1:1:1:1", 1)
 // / #if gtest_version <= 1.7.0
 ));
 /// #else gtest_version > 1.8.0