[Custom] Add an example scaffolding
authorJihoon Lee <jhoon.it.lee@samsung.com>
Wed, 18 Nov 2020 02:30:40 +0000 (11:30 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Mon, 30 Nov 2020 09:37:41 +0000 (18:37 +0900)
Add a layer example that depends on the user's custom code
This patch generates scaffolding to the `Application/Custom` folder

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

Signed-off-by: Jihoon Lee <jhoon.it.lee@samsung.com>
Applications/Custom/LayerClient/README.md [new file with mode: 0644]
Applications/Custom/LayerClient/jni/Android.mk [new file with mode: 0644]
Applications/Custom/LayerClient/jni/Application.mk [new file with mode: 0644]
Applications/Custom/LayerClient/jni/main.cpp [new file with mode: 0644]
Applications/Custom/LayerClient/jni/meson.build [new file with mode: 0644]
Applications/Custom/LayerClient/jni/pow.cpp [new file with mode: 0644]
Applications/Custom/LayerClient/jni/pow.h [new file with mode: 0644]
Applications/Custom/LayerClient/res/custom_layer_client.ini [new file with mode: 0644]
Applications/Custom/README.md [new file with mode: 0644]
Applications/meson.build

diff --git a/Applications/Custom/LayerClient/README.md b/Applications/Custom/LayerClient/README.md
new file mode 100644 (file)
index 0000000..555a1c2
--- /dev/null
@@ -0,0 +1,4 @@
+# LayerClient Example
+
+This application demonstrates how to create a custom layer and register inside client-side code
+
diff --git a/Applications/Custom/LayerClient/jni/Android.mk b/Applications/Custom/LayerClient/jni/Android.mk
new file mode 100644 (file)
index 0000000..5cd3da0
--- /dev/null
@@ -0,0 +1,70 @@
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+# ndk path
+ifndef ANDROID_NDK
+$(error ANDROID_NDK is not defined!)
+endif
+
+ifndef NNTRAINER_ROOT
+NNTRAINER_ROOT := $(LOCAL_PATH)/../../../..
+endif
+
+NNTRAINER_INCLUDES := $(NNTRAINER_ROOT)/nntrainer \
+       $(NNTRAINER_ROOT)/nntrainer/dataset \
+       $(NNTRAINER_ROOT)/nntrainer/models \
+       $(NNTRAINER_ROOT)/nntrainer/layers \
+       $(NNTRAINER_ROOT)/nntrainer/optimizers \
+       $(NNTRAINER_ROOT)/nntrainer/tensor \
+       $(NNTRAINER_ROOT)/api \
+       $(NNTRAINER_ROOT)/api/ccapi/include \
+       $(NNTRAINER_ROOT)/api/capi/include/platform
+
+NNTRAINER_APPLICATION := $(NNTRAINER_ROOT)/Applications
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := nntrainer
+LOCAL_SRC_FILES := $(NNTRAINER_ROOT)/libs/$(TARGET_ARCH_ABI)/libnntrainer.so
+
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := ccapi-nntrainer
+LOCAL_SRC_FILES := $(NNTRAINER_ROOT)/libs/$(TARGET_ARCH_ABI)/libccapi-nntrainer.so
+
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_MODULE := app_utils
+LOCAL_SRC_FILES := $(NNTRAINER_ROOT)/Applications/utils/libs/$(TARGET_ARCH_ABI)/libapp_utils.so
+APP_UTILS_INCLUDES := $(NNTRAINER_ROOT)/Applications/utils/jni/includes
+
+include $(PREBUILT_SHARED_LIBRARY)
+
+include $(CLEAR_VARS)
+
+LOCAL_ARM_NEON := true
+LOCAL_CFLAGS += -std=c++14 -Ofast -mcpu=cortex-a53 -Ilz4-nougat/lib
+LOCAL_LDFLAGS += -Llz4-nougat/lib/obj/local/$(TARGET_ARCH_ABI)/
+LOCAL_CXXFLAGS += -std=c++14
+LOCAL_CFLAGS += -pthread -fexceptions
+LOCAL_LDFLAGS += -fopenmp -fexceptions
+LOCAL_MODULE_TAGS := optional
+LOCAL_ARM_MODE := arm
+LOCAL_MODULE := nntrainer_layer_client_example
+LOCAL_LDLIBS := -llog
+
+LOCAL_SRC_FILES := main.cpp
+
+# todo: make this application only depending on ccapi
+LOCAL_SHARED_LIBRARIES := nntrainer ccapi-nntrainer app_utils
+
+LOCAL_C_INCLUDES += $(NNTRAINER_INCLUDES) $(APP_UTILS_INCLUDES)
+
+include $(BUILD_EXECUTABLE)
+
+
diff --git a/Applications/Custom/LayerClient/jni/Application.mk b/Applications/Custom/LayerClient/jni/Application.mk
new file mode 100644 (file)
index 0000000..228f653
--- /dev/null
@@ -0,0 +1,3 @@
+APP_ABI = arm64-v8a
+APP_STL = c++_shared
+APP_PLATFORM=android-24
diff --git a/Applications/Custom/LayerClient/jni/main.cpp b/Applications/Custom/LayerClient/jni/main.cpp
new file mode 100644 (file)
index 0000000..e0f57f5
--- /dev/null
@@ -0,0 +1,65 @@
+// SPDX-License-Identifier: Apache-2.0
+/**
+ * Copyright (C) 2020 Jihoon Lee <jhoon.it.lee@samsung.com>
+ *
+ * @file   main.cpp
+ * @date   16 November 2020
+ * @brief  This file contains the execution part of LayerClient example
+ * @see    https://github.com/nnstreamer/nntrainer
+ * @author Jihoon Lee <jhoon.it.lee@samsung.com>
+ * @bug    No known bugs except for NYI items
+ *
+ */
+#include <iostream>
+#include <memory>
+
+#include <model.h>
+
+#include <pow.h>
+
+#define BATCH_SIZE 10
+#define FEATURE_SIZE 100
+#define NUM_CLASS 10
+
+/**
+ * @brief      get data which size is batch for train
+ * @param[out] outVec
+ * @param[out] outLabel
+ * @param[out] last if the data is finished
+ * @param[in] user_data private data for the callback
+ * @retval status for handling error
+ */
+int constant_generator_cb(float **outVec, float **outLabel, bool *last,
+                          void *user_data) {
+  static int count = 0;
+  unsigned int i;
+  unsigned int data_size = BATCH_SIZE * FEATURE_SIZE;
+
+  for (i = 0; i < data_size; ++i) {
+    outVec[0][i] = 1.0f;
+  }
+
+  outLabel[0][0] = 1.0f;
+  for (i = 0; i < NUM_CLASS - 1; ++i) {
+    outLabel[0][i] = 0.0f;
+  }
+
+  if (count == 10) {
+    *last = true;
+    count = 0;
+  } else {
+    *last = false;
+    count++;
+  }
+
+  return ML_ERROR_NONE;
+}
+
+int main(int argc, char *argv[]) {
+  /**< add argc */
+  auto model = ml::train::createModel(ml::train::ModelType::NEURAL_NET);
+
+  model->loadFromConfig("..model.ini");
+
+  std::cout << "This is an example scaffolding of LayerClient";
+}
diff --git a/Applications/Custom/LayerClient/jni/meson.build b/Applications/Custom/LayerClient/jni/meson.build
new file mode 100644 (file)
index 0000000..6add91f
--- /dev/null
@@ -0,0 +1,19 @@
+res_path = meson.current_source_dir() / '..' / 'res'
+
+layer_client_sources = [
+  'main.cpp'
+]
+
+layer_client_inc = include_directories('.')
+
+ini_in_path = res_path / 'custom_layer_client.ini'
+ini_out_path = meson.build_root() / 'custom_layer_client.ini'
+
+run_command('cp', ini_in_path, ini_out_path)
+
+e = executable('layer_client',
+  layer_client_sources,
+  dependencies: [app_utils_dep, iniparser_dep, nntrainer_dep, nntrainer_ccapi_dep],
+  install: get_option('install-app'),
+  install_dir: application_install_dir
+)
diff --git a/Applications/Custom/LayerClient/jni/pow.cpp b/Applications/Custom/LayerClient/jni/pow.cpp
new file mode 100644 (file)
index 0000000..a985430
--- /dev/null
@@ -0,0 +1,13 @@
+// SPDX-License-Identifier: Apache-2.0
+/**
+ * Copyright (C) 2020 Jihoon Lee <jhoon.it.lee@samsung.com>
+ *
+ * @file   pow.cpp
+ * @date   16 November 2020
+ * @brief  This file contains the simple pow2 layer which squares input
+ * elements.
+ * @see    https://github.com/nnstreamer/nntrainer
+ * @author Jihoon Lee <jhoon.it.lee@samsung.com>
+ * @bug    No known bugs except for NYI items
+ *
+ */
diff --git a/Applications/Custom/LayerClient/jni/pow.h b/Applications/Custom/LayerClient/jni/pow.h
new file mode 100644 (file)
index 0000000..f2467b6
--- /dev/null
@@ -0,0 +1,119 @@
+// SPDX-License-Identifier: Apache-2.0
+/**
+ * Copyright (C) 2020 Jihoon Lee <jhoon.it.lee@samsung.com>
+ *
+ * @file   pow.h
+ * @date   16 November 2020
+ * @brief  This file contains the simple pow2 layer which squares input
+ * elements.
+ * @see    https://github.com/nnstreamer/nntrainer
+ * @author Jihoon Lee <jhoon.it.lee@samsung.com>
+ * @bug    No known bugs except for NYI items
+ *
+ */
+
+#ifndef __POW_LAYER_H__
+#define __POW_LAYER_H__
+
+#include <layer.h>
+#include <tensor.h>
+
+namespace custom {
+class PowLayer : public ml::train::Layer {
+public:
+  /**
+   * @brief Construct a new Pow Layer object that does elementwise power
+   *
+   * @param exponent_ exponent
+   */
+  PowLayer(float exponent_ = 1) : exponent(exponent_) {}
+
+  /**
+   * @brief Destroy the Pow Layer object
+   *
+   */
+  ~PowLayer();
+
+  /**
+   * @brief     set Property of layer
+   * @param[in] values values of property
+   * @retval #ML_ERROR_NONE Successful.
+   * @retval #ML_ERROR_INVALID_PARAMETER invalid parameter.
+   */
+  int setProperty(std::vector<std::string> values) {
+    /**< NYI */
+    return 1;
+  }
+
+  /**
+   * @brief Set the Property by propertyType, this is not used in this demo
+   *
+   * @param type property type
+   * @param value value
+   */
+  void setProperty(const ml::train::Layer::PropertyType type,
+                   const std::string &value = "") {
+    /**< NOT USED */
+  }
+
+  /**
+   * @brief check if hyperparameter is valid
+   *
+   * @return int ML_ERROR_NONE if successful
+   */
+  int checkValidataion() { return ML_ERROR_NONE; }
+
+  /**
+   * @brief Get the Loss bound to the object
+   *
+   * @return float
+   */
+  float getLoss() { return 0.0f; }
+
+  /**
+   * @brief nntrainer forwarding function
+   *
+   * @param in input tensors
+   * @return nntrainer::sharedConstTensors output tensors
+   */
+  nntrainer::sharedConstTensors forwarding(nntrainer::sharedConstTensors in) {
+    return in;
+  }
+
+  /**
+   * @brief nntrainer backwaridng function
+   *
+   * @param in input tensors
+   * @param iteration number of iterations
+   * @return nntrainer::sharedConstTensors output tensors
+   */
+  nntrainer::sharedConstTensors backwarding(nntrainer::sharedConstTensors in,
+                                            int iteration) {
+    return in;
+  }
+
+  /**
+   * @brief initialize function
+   *
+   * @return int ML_ERROR_NONE if successful
+   */
+  int initialize() { return 1; }
+
+  /**
+   * @brief Get the Type object
+   *
+   * @return const std::string
+   */
+  const std::string getType() const { return PowLayer::type; }
+
+  static const std::string type;
+
+private:
+  float exponent;
+};
+
+const std::string PowLayer::type = "pow";
+
+} // namespace custom
+
+#endif /* __POW_LAYER_H__ */
diff --git a/Applications/Custom/LayerClient/res/custom_layer_client.ini b/Applications/Custom/LayerClient/res/custom_layer_client.ini
new file mode 100644 (file)
index 0000000..ad9ba43
--- /dev/null
@@ -0,0 +1,20 @@
+# This file will contain model.ini
+# Network Section : Network
+[Model]
+Type = NeuralNetwork
+Learning_rate = 0.001
+Epochs = 30000
+Optimizer = sgd
+Loss = cross
+batch_size = 10
+
+# Layer Section : Name
+[inputlayer]
+Type = InputLayer
+Input_Shape = 1:1:100
+
+[outputlayer]
+Type = fully_connected
+unit = 10
+Bias_initializer = zeros
+Activation = softmax
diff --git a/Applications/Custom/README.md b/Applications/Custom/README.md
new file mode 100644 (file)
index 0000000..e2c8330
--- /dev/null
@@ -0,0 +1,19 @@
+# Application with Custom Object
+
+Applications inside this folder are dedicated to demonstrate how to create custom layers, optimizers or other supported objects.
+
+There are two ways to apply custom object to the code.
+
+1. Create an object as a part of client code and register it to NNTrainer on the client code.
+  Easy to write, less portable
+2. Create an object as a dynamic library and NNTrainer load the dynamic library.
+  Portable, more configurations
+
+
+## Structure of the folder
+
+`*Client` demonstrates how to generate an object inside a client code and register on the fly.
+For example, `LayerClient` will demo about how to write a custom layer and register it.
+
+`*Plugin` demonstrates how to generate an object inside a plugin code and register on the fly.
+For example, `OptimizerPlugin` will demo about how to create a custom optimizer as a pluggable library.
index 103296b..947db73 100644 (file)
@@ -8,3 +8,4 @@ subdir('VGG/jni')
 subdir('ReinforcementLearning/DeepQ/jni')
 subdir('TransferLearning/CIFAR_Classification/jni')
 subdir('TransferLearning/Draw_Classification/jni')
+subdir('Custom/LayerClient/jni')