[Props] Implement activation property
authorJihoon Lee <jhoon.it.lee@samsung.com>
Tue, 7 Sep 2021 09:51:14 +0000 (18:51 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Fri, 10 Sep 2021 06:16:26 +0000 (15:16 +0900)
This patch implements activation property by enum

**Additional changes**
- TimeDistribute property is now handled at finalize()

**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>
nntrainer/graph/network_graph.cpp
nntrainer/layers/acti_func.h
nntrainer/layers/activation_layer.cpp
nntrainer/layers/activation_layer.h
nntrainer/layers/centroid_knn.h
nntrainer/layers/common_properties.h
nntrainer/layers/layer_node.cpp
nntrainer/layers/layer_node.h
nntrainer/utils/base_properties.h

index 842f8a825f99174563382a0f5c88d7d85f232eca..fb33e7539561b677214f3f06331c91bdac21b9a4 100644 (file)
@@ -196,7 +196,9 @@ int NetworkGraph::realizeActivationType(
     lnode->setProperty({"distribute=true"});
   }
 
-  lnode->setProperty({"activation=" + ActivationTypeStr[(unsigned int)act]});
+  props::Activation act_prop;
+  act_prop.set(act);
+  lnode->setProperty({"activation=" + to_string(act_prop)});
   in_node->setProperty({"activation=none"});
 
   lnode->setInputLayers({in_node->getName()});
@@ -297,7 +299,6 @@ int NetworkGraph::addLossLayer(const std::string &loss_type_) {
 }
 
 void NetworkGraph::setOutputLayers() {
-
   for (auto iter_idx = cbegin(); iter_idx != cend(); iter_idx++) {
     auto &layer_idx = *iter_idx;
     for (auto iter_i = cbegin(); iter_i != cend(); iter_i++) {
@@ -354,15 +355,14 @@ int NetworkGraph::checkCompiledGraph() {
 }
 
 int NetworkGraph::realizeGraph() {
-
   int status = ML_ERROR_NONE;
 
   addDefaultInputLayers();
 
   /**
    * invariant: the new realized nodes are added to the end,
-   * otherwise this iteration becomes invalid. So, every iteration must be fresh
-   * iterator as vector resize invalidates all the iterators.
+   * otherwise this iteration becomes invalid. So, every iteration must be
+   * fresh iterator as vector resize invalidates all the iterators.
    */
   for (unsigned int i = 0; i < graph.size(); ++i) {
     auto const &lnode = LNODE(*(cbegin() + i));
@@ -511,7 +511,6 @@ std::vector<std::shared_ptr<LayerNode>> NetworkGraph::getLayerNodes() const {
 
 void NetworkGraph::extendGraph(std::vector<std::shared_ptr<LayerNode>> ex_graph,
                                std::string &prefix) {
-
   if (compiled)
     throw std::runtime_error("Cannot modify graph after compile");
 
index b7c4e81338ba858a4575f30060af1dfab0887364..8aaf5294a76d7aff0f8563f44c2ee44db3529637 100644 (file)
 #define __ACTI_FUNC_H__
 #ifdef __cplusplus
 
+#include <common_properties.h>
 #include <tensor.h>
 
 namespace nntrainer {
 
-/**
- * @brief     Enumeration of activation function type
- */
-enum class ActivationType {
-  ACT_TANH,    /** tanh */
-  ACT_SIGMOID, /** sigmoid */
-  ACT_RELU,    /** ReLU */
-  ACT_SOFTMAX, /** softmax */
-  ACT_NONE,    /** no op */
-  ACT_UNKNOWN  /** unknown */
-};
-
 /**
  * @brief     Activation enum to string map
  */
index e0bd297585ca20a322c3a973c8a18891a21d9dac..5ac2e1c16b543318030f01e8c94c492a4718e949 100644 (file)
 
 #include <activation_layer.h>
 #include <blas_interface.h>
+#include <common_properties.h>
 #include <lazy_tensor.h>
 #include <nntrainer_error.h>
 #include <nntrainer_log.h>
+#include <node_exporter.h>
 #include <parse_util.h>
 #include <tensor.h>
 #include <util_func.h>
 
 namespace nntrainer {
+ActivationLayer::ActivationLayer() :
+  Layer(),
+  activation_props(new PropTypes(props::Activation())) {
+  acti_func.setActiFunc(ActivationType::ACT_NONE);
+}
 
 static constexpr size_t SINGLE_INOUT_IDX = 0;
 
 void ActivationLayer::finalize(InitLayerContext &context) {
+  auto &act = std::get<props::Activation>(*activation_props);
+  NNTR_THROW_IF(act.empty(), std::invalid_argument)
+    << "activation has not been set!";
+  acti_func.setActiFunc(act.get());
   context.setOutputDimensions(context.getInputDimensions());
 }
 
@@ -49,69 +60,15 @@ void ActivationLayer::calcDerivative(RunLayerContext &context) {
   acti_func.run_prime_fn(out, ret, deriv);
 }
 
-void ActivationLayer::setProperty(const std::vector<std::string> &values) {
-  /// @todo: deprecate this in favor of loadProperties
-  for (unsigned int i = 0; i < values.size(); ++i) {
-    std::string key;
-    std::string value;
-    std::stringstream ss;
-
-    if (getKeyValue(values[i], key, value) != ML_ERROR_NONE) {
-      throw std::invalid_argument("Error parsing the property: " + values[i]);
-    }
-
-    if (value.empty()) {
-      ss << "value is empty: key: " << key << ", value: " << value;
-      throw std::invalid_argument(ss.str());
-    }
-
-    /// @note this calls derived setProperty if available
-    setProperty(key, value);
-  }
-}
-
-void ActivationLayer::setProperty(const std::string &type_str,
-                                  const std::string &value) {
-  using PropertyType = nntrainer::Layer::PropertyType;
-  nntrainer::Layer::PropertyType type =
-    static_cast<nntrainer::Layer::PropertyType>(parseLayerProperty(type_str));
-
-  switch (type) {
-  case PropertyType::activation: {
-    acti_func.setActiFunc((ActivationType)parseType(value, TOKEN_ACTI));
-  } break;
-  default:
-    std::string msg =
-      "[Layer] Unknown Layer Property Key for value " + std::string(value);
-    throw exception::not_supported(msg);
-  }
-}
-
-int ActivationLayer::setActivation(
-  std::function<Tensor &(Tensor const &, Tensor &)> const &activation_fn,
-  std::function<Tensor &(Tensor &, Tensor &, Tensor const &)> const
-    &activation_prime_fn) {
-  acti_func.setActivation(activation_fn, activation_prime_fn);
-
-  return ML_ERROR_NONE;
+void ActivationLayer::exportTo(Exporter &exporter,
+                               const ExportMethods &method) const {
+  exporter.saveResult(*activation_props, method, this);
 }
 
-int ActivationLayer::setActivation(
-  std::function<Tensor &(Tensor const &, Tensor &)> const &activation_fn,
-  std::function<Tensor &(Tensor &, Tensor &)> const &activation_prime_fn) {
-
-  acti_func.setActivation(activation_fn, activation_prime_fn);
-
-  return ML_ERROR_NONE;
-}
-
-int ActivationLayer::setActivation(
-  std::function<float(float const)> const &activation_fn,
-  std::function<float(float const)> const &activation_prime_fn) {
-
-  acti_func.setActivation(activation_fn, activation_prime_fn);
-
-  return ML_ERROR_NONE;
+void ActivationLayer::setProperty(const std::vector<std::string> &values) {
+  auto left = loadProperties(values, *activation_props);
+  NNTR_THROW_IF(!left.empty(), std::invalid_argument)
+    << "Failed to set property";
 }
 
 }; // namespace nntrainer
index 637a8dc0a136a17f0c0bac7edf7105db0b8a65aa..52e1e2d804542abe75ce1f7a728153dd219d9d0d 100644 (file)
 #define __ACTIVATION_LAYER_H__
 #ifdef __cplusplus
 
+#include <memory>
+
 #include <acti_func.h>
 #include <layer_devel.h>
 
 namespace nntrainer {
 
+namespace props {
+class ActivationType;
+
+} // namespace props
+
 /**
  * @class   Activation Layer
  * @brief   Activation Layer
@@ -30,9 +37,7 @@ public:
   /**
    * @brief     Constructor of Activation Layer
    */
-  ActivationLayer() : Layer() {
-    acti_func.setActiFunc(ActivationType::ACT_NONE);
-  }
+  ActivationLayer();
 
   /**
    * @brief     Destructor of Activation Layer
@@ -62,8 +67,7 @@ public:
   /**
    * @copydoc Layer::exportTo(Exporter &exporter, ExportMethods method)
    */
-  void exportTo(Exporter &exporter,
-                const ExportMethods &method) const override {}
+  void exportTo(Exporter &exporter, const ExportMethods &method) const override;
 
   /**
    * @copydoc Layer::getType()
@@ -83,61 +87,11 @@ public:
   inline static const std::string type = "activation";
 
 private:
-  ActiFunc
-    acti_func; /**< activation function designating the activation operation */
+  using PropTypes = std::tuple<props::Activation>;
 
-  /**
-   * @brief setActivation by custom activation function
-   * @note  apply derivative as this activation_prime_fn does not utilize
-   * derivative
-   * @param[in] std::function<Tensor(Tensor const &, Tensor &)> activation_fn
-   * activation function to be used
-   * @param[in] std::function<Tensor(Tensor const &, Tensor &)>
-   * activation_prime_fn activation_prime_function to be used
-   * @retval #ML_ERROR_NONE when successful
-   */
-  int setActivation(
-    std::function<Tensor &(Tensor const &, Tensor &)> const &activation_fn,
-    std::function<Tensor &(Tensor &, Tensor &)> const &activation_prime_fn);
+  std::unique_ptr<PropTypes> activation_props; /**< activation props */
 
-  /**
-   * @brief setActivation by custom activation function
-   * @note  derivative not applied here as this activation_prime_fn applies
-   * derivative itself
-   * @param[in] std::function<Tensor(Tensor const &, Tensor &)> activation_fn
-   * activation function to be used
-   * @param[in] std::function<Tensor(Tensor const &, Tensor &, Tensor const &)>
-   * activation_prime_fn activation_prime_function to be used
-   * @retval #ML_ERROR_NONE when successful
-   */
-  int setActivation(
-    std::function<Tensor &(Tensor const &, Tensor &)> const &activation_fn,
-    std::function<Tensor &(Tensor &, Tensor &, Tensor const &)> const
-      &activation_prime_fn);
-
-  /**
-   * @brief setActivation by custom activation function
-   * @note  apply derivative as this activation_prime_fn does not utilize
-   * derivative
-   * @param[in] std::function<float(float const &)> activation_fn activation
-   *            function to be used
-   * @param[in] std::function<float(float const &)> activation_prime_fn
-   *            activation_prime_function to be used
-   * @retval #ML_ERROR_NONE when successful
-   */
-  int setActivation(
-    std::function<float(float const)> const &activation_fn,
-    std::function<float(float const)> const &activation_prime_fn);
-
-  /**
-   * @brief setProperty by type and value separated
-   * @param[in] type property type to be passed
-   * @param[in] value value to be passed
-   * @exception exception::not_supported     when property type is not valid for
-   * the particular layer
-   * @exception std::invalid_argument invalid argument
-   */
-  void setProperty(const std::string &type, const std::string &value);
+  ActiFunc acti_func; /**< activation function from activation type */
 };
 
 } // namespace nntrainer
index 83208d601d9b90a2bd7d380cbee567575b39f186..200493b7e5f70ee748fea5271c07f6d8f6ff5a19 100644 (file)
@@ -11,7 +11,6 @@
  * @bug    No known bugs except for NYI items
  *
  */
-
 #ifndef __CENTROID_KNN_H__
 #define __CENTROID_KNN_H__
 #include <string>
index afeb3d4de9959950a4710c7896f449512d45f087..02d6783840b2e6f9c1a3370e831a3b62008ec64f 100644 (file)
  * @author Jihoon Lee <jhoon.it.lee@samsung.com>
  * @bug    No known bugs except for NYI items
  */
-
-#include <string>
+#ifndef __COMMON_PROPERTIES_H__
+#define __COMMON_PROPERTIES_H__
 
 #include <array>
-#include <base_properties.h>
 #include <fstream>
+#include <string>
 
-#ifndef __COMMON_PROPERTIES_H__
-#define __COMMON_PROPERTIES_H__
+#include <base_properties.h>
 
 namespace nntrainer {
 
+/**
+ * @brief     Enumeration of activation function type
+ * @note      Upon changing this enum, ActivationTypeInfo must be changed
+ * accordingly
+ */
+enum class ActivationType {
+  ACT_TANH,    /** tanh */
+  ACT_SIGMOID, /** sigmoid */
+  ACT_RELU,    /** ReLU */
+  ACT_SOFTMAX, /** softmax */
+  ACT_NONE,    /** no op */
+  ACT_UNKNOWN  /** unknown */
+};
+
 namespace props {
 
 /**
@@ -316,6 +329,30 @@ public:
    */
   bool isValid(const unsigned int &v) const override;
 };
+
+/******** below section is for enumerations ***************/
+/**
+ * @brief     Enumeration of activation function type
+ */
+struct ActivationTypeInfo {
+  using Enum = nntrainer::ActivationType;
+  static constexpr std::initializer_list<Enum> EnumList = {
+    Enum::ACT_TANH,    Enum::ACT_SIGMOID, Enum::ACT_RELU,
+    Enum::ACT_SOFTMAX, Enum::ACT_NONE,    Enum::ACT_UNKNOWN};
+
+  static constexpr const char *EnumStr[] = {"tanh",    "sigmoid", "relu",
+                                            "softmax", "none",    "unknown"};
+};
+
+/**
+ * @brief Activation Enumeration Information
+ *
+ */
+class Activation final : public EnumProperty<ActivationTypeInfo> {
+public:
+  using prop_tag = enum_class_prop_tag;
+  static constexpr const char *key = "activation";
+};
 } // namespace props
 } // namespace nntrainer
 
index 25794cb3e2178da181bf47221491f15470737042..72cee0116db09b3ecff5b129fb048437785a68ca 100644 (file)
@@ -28,7 +28,6 @@
 namespace nntrainer {
 
 namespace props {
-class ActivationType;
 
 /**
  * @brief Flatten property, true if needs flatten layer afterwards
@@ -49,9 +48,6 @@ public:
   Distribute() : Property<bool>() {}
   static constexpr const char *key = "distribute";
   using prop_tag = bool_prop_tag;
-  bool isValid(const bool &v) const {
-    return empty() || !get();
-  } /**< distribute=true can be set strictly one time */
 };
 
 /**
@@ -170,11 +166,11 @@ createLayerNode(std::unique_ptr<nntrainer::Layer> &&layer,
 
 LayerNode::LayerNode(std::unique_ptr<nntrainer::Layer> &&l) :
   layer(std::move(l)),
-  activation_type(ActivationType::ACT_NONE),
   run_context(nullptr),
-  layer_node_props(new PropsType(props::Name(), props::Flatten(),
-                                 props::Distribute(), props::Trainable(), {},
-                                 {})),
+  layer_node_props(new PropsType(props::Name(), props::Distribute(),
+                                 props::Trainable(), {}, {})),
+  layer_node_props_realization(
+    new RealizationPropsType(props::Flatten(), props::Activation())),
   loss(new props::Loss()),
   regularization_loss(0.0f),
   exec_order({0, 0, 0}) {
@@ -184,75 +180,10 @@ LayerNode::LayerNode(std::unique_ptr<nntrainer::Layer> &&l) :
 }
 
 void LayerNode::setProperty(const std::vector<std::string> &properties) {
-  bool already_distributed =
-    !std::get<props::Distribute>(*layer_node_props).empty() &&
-    std::get<props::Distribute>(*layer_node_props).get();
   auto left_properties = loadProperties(properties, *layer_node_props);
-
-  /// note that setting distribute is only allowed for one time.
-  /// until we have layerNode::finalize and must not except timedist layer
-  if (getDistribute() && !already_distributed) {
-    auto &ac = nntrainer::AppContext::Global();
-    std::unique_ptr<nntrainer::Layer> dlayer =
-      ac.createObject<nntrainer::Layer>(TimeDistLayer::type);
-    if (dlayer.get() == nullptr)
-      throw std::invalid_argument("Error creating time distribution layer");
-    auto *time_dist_layer = dynamic_cast<TimeDistLayer *>(dlayer.get());
-    if (time_dist_layer == nullptr)
-      throw std::invalid_argument("Error casting to time distribution layer");
-    time_dist_layer->setDistLayer(std::move(layer));
-    layer = std::move(dlayer);
-  }
-
-  std::vector<std::string> remainder;
-  /// @todo: deprecate this in favor of loadProperties
-  for (unsigned int i = 0; i < left_properties.size(); ++i) {
-
-    std::string key;
-    std::string value;
-    std::stringstream ss;
-
-    if (getKeyValue(left_properties[i], key, value) != ML_ERROR_NONE) {
-      throw std::invalid_argument("Error parsing the property: " +
-                                  left_properties[i]);
-    }
-
-    if (value.empty()) {
-      ss << "value is empty: key: " << key << ", value: " << value;
-      throw std::invalid_argument(ss.str());
-    }
-
-    /// @note this calls derived setProperty if available
-    if (!setProperty(key, value)) {
-      remainder.push_back(left_properties[i]);
-    }
-  }
-
-  layer->setProperty(remainder);
-}
-
-bool LayerNode::setProperty(const std::string &key, const std::string &value) {
-  using PropertyType = nntrainer::Layer::PropertyType;
-
-  PropertyType type = static_cast<PropertyType>(parseLayerProperty(key));
-  switch (type) {
-  case PropertyType::activation: {
-    setActivation((ActivationType)parseType(value, TOKEN_ACTI));
-    if (getType() == ActivationLayer::type) {
-      ml_logi("Set property delegated to activation layer");
-      return false;
-    }
-    break;
-  }
-  case PropertyType::num_inputs: {
-    ml_logw("Deprecated property: %s", key.c_str());
-    break;
-  }
-  default:
-    return false;
-  }
-
-  return true;
+  left_properties =
+    loadProperties(left_properties, *layer_node_props_realization);
+  layer->setProperty(left_properties);
 }
 
 const std::string LayerNode::getName() const noexcept {
@@ -279,7 +210,14 @@ std::ostream &operator<<(std::ostream &out, const LayerNode &l) {
   return out;
 }
 
-ActivationType LayerNode::getActivationType() const { return activation_type; }
+ActivationType LayerNode::getActivationType() const {
+  auto &act_prop = std::get<props::Activation>(*layer_node_props_realization);
+  if (act_prop.empty()) {
+    return ActivationType::ACT_NONE;
+  }
+
+  return act_prop;
+}
 
 unsigned int LayerNode::getNumInputConnections() const {
   auto &input_layers =
@@ -297,14 +235,7 @@ ActivationType LayerNode::getActivationToBeRealized() const {
   if (getType() == ActivationLayer::type)
     return ActivationType::ACT_NONE;
   else
-    return activation_type;
-}
-
-void LayerNode::setActivation(ActivationType activation) {
-  if (activation == ActivationType::ACT_UNKNOWN) {
-    throw std::invalid_argument("Error:have to specify activation function");
-  }
-  activation_type = activation;
+    return getActivationType();
 }
 
 const std::string LayerNode::getType() const { return getLayer()->getType(); }
@@ -314,7 +245,7 @@ bool LayerNode::getTrainable() const {
 }
 
 bool LayerNode::getFlatten() const {
-  auto &flatten = std::get<props::Flatten>(*layer_node_props);
+  auto &flatten = std::get<props::Flatten>(*layer_node_props_realization);
   if (flatten.empty()) {
     return false;
   }
@@ -330,15 +261,15 @@ bool LayerNode::getDistribute() const {
 }
 
 const nntrainer::Layer *LayerNode::getLayer() const {
-  if (getDistribute())
-    return ((TimeDistLayer *)(layer.get()))->getDistLayer();
+  if (run_context && getDistribute())
+    return static_cast<TimeDistLayer *>(layer.get())->getDistLayer();
   else
     return layer.get();
 }
 
 nntrainer::Layer *LayerNode::getLayer() {
-  if (getDistribute())
-    return ((TimeDistLayer *)(layer.get()))->getDistLayer();
+  if (run_context && getDistribute())
+    return static_cast<TimeDistLayer *>(layer.get())->getDistLayer();
   else
     return layer.get();
 }
@@ -439,9 +370,14 @@ void LayerNode::save(std::ofstream &file) const {
  * @brief     Finalize creating the layer node
  */
 InitLayerContext LayerNode::finalize(const std::vector<TensorDim> &input_dims) {
+  /** Create init context right before finalize */
+  if (run_context)
+    throw std::runtime_error("Finalizing a layer which is already finalized");
+
   std::vector<TensorDim> actual_input_dims;
   auto &prop_dims = std::get<std::vector<props::InputShape>>(*layer_node_props);
 
+  /** prepare input dimensions */
   if (!input_dims.empty()) {
     actual_input_dims = input_dims;
     if (hasInputShapeProperty()) {
@@ -456,6 +392,7 @@ InitLayerContext LayerNode::finalize(const std::vector<TensorDim> &input_dims) {
     NNTR_THROW_IF(!hasInputShapeProperty(), std::invalid_argument)
       << "if input dims not given, input shapes must be given by the user as "
          "property";
+    /// arguably, below check can go away
     NNTR_THROW_IF(prop_dims.size() != 1, std::invalid_argument)
       << "input shapes must be one if connection is not given but given "
          "dimesions size of: "
@@ -475,6 +412,25 @@ InitLayerContext LayerNode::finalize(const std::vector<TensorDim> &input_dims) {
   if (run_context)
     throw std::runtime_error("Finalizing a layer which is already finalized");
 
+  /** manipulate layers if required */
+  if (getType() == ActivationLayer::type) {
+    auto &act_prop = std::get<props::Activation>(*layer_node_props_realization);
+    if (!act_prop.empty()) {
+      layer->setProperty({"activation=" + to_string(act_prop)});
+    }
+  }
+  if (getType() != TimeDistLayer::type && getDistribute()) {
+    std::unique_ptr<TimeDistLayer> dlayer(new TimeDistLayer());
+    NNTR_THROW_IF(!dlayer, std::invalid_argument)
+      << "Error creating time distribution layer";
+    dlayer->setDistLayer(std::move(layer));
+    layer = std::move(dlayer);
+  }
+
+  /// remove flatten and activation since it's already realized
+  layer_node_props_realization = std::make_unique<RealizationPropsType>(
+    props::Flatten(), props::Activation());
+
   auto num_outputs = output_layers.size();
   if (output_layers.empty()) {
     num_outputs = 1;
index 258dfac6077920493d7ed086818e1802e67a123a..69f2307e1c5429d47730df95eca4ce395e708b4e 100644 (file)
@@ -28,7 +28,6 @@
 #include <tuple>
 #include <vector>
 
-#include <acti_func.h>
 #include <graph_node.h>
 #include <layer.h>
 #include <layer_context.h>
@@ -46,10 +45,10 @@ namespace props {
 class Name;
 class Distribute;
 class Flatten;
-class ActivationType;
 class Loss;
 class InputLayer;
 class InputShape;
+class Activation;
 } // namespace props
 
 /**
@@ -597,8 +596,6 @@ private:
     layer; /**< The actual object in the graph node */
 
   std::vector<std::string> output_layers; /**< output layer names */
-  ActivationType
-    activation_type; /**< activation applied to the output of this node */
 
   std::unique_ptr<RunLayerContext>
     run_context; /**< context required for running/execution of the layer. This
@@ -607,29 +604,27 @@ upon final creation. Editing properties of the layer after init will not the
 properties in the context/graph unless intended. */
 
   using PropsType =
-    std::tuple<props::Name, props::Flatten, props::Distribute, props::Trainable,
+    std::tuple<props::Name, props::Distribute, props::Trainable,
                std::vector<props::InputLayer>, std::vector<props::InputShape>>;
+
+  using RealizationPropsType = std::tuple<props::Flatten, props::Activation>;
+  /** these realization properties results in addition of new layers, hence
+   * skipped in generation of model architecture as the correspondingly layer
+   * itself is added. Distribute is also a property which is realized, but as it
+   * doesn't add new layer, it is saved. */
+
   /**
    * These properties are set for the layer by the user but are intercepted
    * and used in the node which forms the basic element of the graph.
    */
   std::unique_ptr<PropsType> layer_node_props; /**< properties for the node */
-  std::unique_ptr<props::Loss> loss;           /**< loss */
+  std::unique_ptr<RealizationPropsType>
+    layer_node_props_realization;    /**< properties for the node */
+  std::unique_ptr<props::Loss> loss; /**< loss */
   float regularization_loss;
   ExecutionOrder exec_order; /**< order/location of execution for this node
                                    in forward and backwarding operations */
 
-  /**
-   * @brief setProperty by PropertyType
-   * @note By passing empty string, this can validate if @a type is valid
-   * @param[in] key property type to be passed
-   * @param[in] value value to be passed, if empty string is passed, do nothing
-   * but throws error when @a type is invalid
-   * @return true if the property can be captured, else false
-   * @exception std::invalid_argument invalid argument
-   */
-  bool setProperty(const std::string &key, const std::string &value);
-
   /**
    * @brief   Get the effective layer managed by this layer node
    *
@@ -646,13 +641,6 @@ properties in the context/graph unless intended. */
    */
   nntrainer::Layer *getLayer();
 
-  /**
-   * @brief     Activation Setter
-   * @param[in] activation activation type
-   * @throw std::invalid_argument when ActivationType is unknown
-   */
-  void setActivation(ActivationType activation);
-
   /**
    * @brief anchor point to override if PRINT_SHAPE_INFO is enabled for
    * Layer::print()
index a186a6b88cd8afff7569c3bb552042bf198deee0..3cba6d16f33c7cfa130245978c7fcca2cba66a16 100644 (file)
@@ -9,6 +9,9 @@
  * @author Jihoon Lee <jhoon.it.lee@samsung.com>
  * @bug No known bugs except for NYI items
  */
+#ifndef __BASE_PROPERTIES_H__
+#define __BASE_PROPERTIES_H__
+
 #include <array>
 #include <memory>
 #include <regex>
@@ -20,9 +23,6 @@
 #include <props_util.h>
 #include <tensor_dim.h>
 
-#ifndef __BASE_PROPERTIES_H__
-#define __BASE_PROPERTIES_H__
-
 /** base and predefined structures */
 
 namespace nntrainer {