[layercontext] Add unsafe methods
authorParichay Kapoor <pk.kapoor@samsung.com>
Wed, 7 Jul 2021 01:11:25 +0000 (10:11 +0900)
committerJijoong Moon <jijoong.moon@samsung.com>
Thu, 22 Jul 2021 11:47:24 +0000 (20:47 +0900)
getGradient methods always perform checks about memory being allocated
for the gradients. However for labels, we donot want to allocate memory
as label is allocated by the dataset. Yet, we still want to able to set
it at the output gradient. So, a getGradientUnsafe is added which
allows returing empty tensor reference so that gradient can be set.

This new interface does not provide new functionality for the layer
developer but rather provides an unsafe method with the existing
functionality.

Signed-off-by: Parichay Kapoor <pk.kapoor@samsung.com>
nntrainer/layers/activation_layer.cpp
nntrainer/layers/layer_context.h
nntrainer/layers/layer_node.cpp
nntrainer/layers/layer_node.h
nntrainer/models/neuralnet.cpp
nntrainer/tensor/var_grad.h

index e7819bca29db21395c6ca5ea19996cf752198d9a..a798851f2a79933df495146daeeb2d3a613036e6 100644 (file)
@@ -47,7 +47,7 @@ void ActivationLayer::calcDerivative(RunLayerContext &context) {
   Tensor &ret = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
   Tensor &out = context.getOutput(SINGLE_INOUT_IDX);
 
-  ret = acti_func.run_prime_fn(out, ret, deriv);
+  acti_func.run_prime_fn(out, ret, deriv);
 }
 
 void ActivationLayer::setProperty(const std::vector<std::string> &values) {
index cddd855c39ff797bd6da1886a18a6bc5c1e02aea..4270653e21f956158ef6956e4b3f14797fb678eb 100644 (file)
@@ -325,6 +325,19 @@ public:
     if (!outputs[idx]->hasGradient())
       throw std::invalid_argument(
         "Requesting gradient for a non-trainable tensor.");
+    return getOutputGradUnsafe(idx);
+  }
+
+  /**
+   * @brief Get the Output Grad tensor object
+   *
+   * @param idx Identifier of the output
+   * @return Tensor& Reference to the output grad tensor
+   *
+   * @note recommended to NOT use this function as a layer developer but rather
+   * use getOutputGrad().
+   */
+  Tensor &getOutputGradUnsafe(unsigned int idx) {
     return outputs[idx]->getGradientRef();
   }
 
index 991a34e6f722f39943e56403ed28dd1bf4a5420d..1a5e03ed629b3165ff4b7a7ee0228edbb4e11cb6 100644 (file)
@@ -427,8 +427,6 @@ void LayerNode::setBatch(unsigned int batch) {
       run_context.setBatch(batch);
       layer->setBatch(run_context, batch);
     } else {
-      for (auto &dim : input_dim)
-        dim.batch(batch);
       init_context.setBatch(batch);
       layer->setBatch(init_context, batch);
     }
index f89ef7fed0b59706e1caa6acbbe98b00fc269185..f58b139ebce0f21845134ec65fcb25a01aa31727 100644 (file)
@@ -328,7 +328,7 @@ public:
    * @brief     Get number of inputs
    * @retval    number of inputs
    */
-  unsigned int getNumInputs() const { return input_dim.size(); }
+  unsigned int getNumInputs() const { return init_context.getNumInputs(); }
 
   /**
    * @brief     Get number of outputs
@@ -462,7 +462,7 @@ public:
    * @brief Get the Weight object
    *
    * @param idx Identifier of the weight
-   * @return Tensor& Reference to the weight tensor
+   * @return Weight& Reference to the weight
    */
   Weight getWeightWrapper(unsigned int idx) {
     if (layerv1 == nullptr) {
@@ -585,6 +585,20 @@ public:
     }
   }
 
+  /**
+   * @brief Get the Output Grad unsafe
+   *
+   * @param idx Identifier of the output
+   * @return Tensor& Reference to the output grad tensor
+   */
+  Tensor &getOutputGradUnsafe(unsigned int idx) {
+    if (layerv1 == nullptr) {
+      return run_context.getOutputGradUnsafe(idx);
+    } else {
+      return getLayer()->getOutputRef()[idx]->getGradientRef();
+    }
+  }
+
   /**
    * @brief     read layer Weight & Bias data from file
    * @param file input file stream
index 92736f4ea288c927cab1b7f11f95e812044a9f69..e606e4dcb079881acc9b14f78bf0185223fc6e88 100644 (file)
@@ -237,13 +237,13 @@ sharedConstTensors NeuralNetwork::forwarding(sharedConstTensors input,
       << " requirements size: " << layer_node->getNumOutputs();
 
     for (unsigned int i = 0; i < layer_node->getNumOutputs(); i++) {
-      layer_node->getOutputGrad(i) = *label[i];
+      layer_node->getOutputGradUnsafe(i) = *label[i];
     }
   };
 
   auto clear_label = [](auto const &layer_node) {
     for (unsigned int i = 0; i < layer_node->getNumOutputs(); i++) {
-      layer_node->getOutputGrad(i) = Tensor();
+      layer_node->getOutputGradUnsafe(i) = Tensor();
     }
   };
 
index 0359c74e0df5a0375a4036bd71ad92df2300a1a4..c4fa320a951ddac81a35320fb38ad420ac59960a 100644 (file)
@@ -84,7 +84,7 @@ public:
     dim(v.getDim()),
     var(std::make_shared<Tensor>(v.getSharedDataTensor(dim, 0, false))),
     grad(std::make_shared<Tensor>(g.getSharedDataTensor(dim, 0, false))),
-    trainable(!g.uninitialized()),
+    need_gradient(!g.uninitialized()),
     alloc_now(v.isAllocated()),
     name(n) {}
 
@@ -131,6 +131,8 @@ public:
     initializeVariable(var_preallocated);
     if (gtrain)
       initializeGradient(grad_preallocated);
+    else
+      grad = std::make_shared<Tensor>();
   }
 
   /**