}
std::vector<sharedConstTensor> out;
- for (auto const &nh :
- getSortedLayerNode(graph.size() - 1)->getObject()->net_hidden)
- out.push_back(MAKE_SHARED_TENSOR(nh->getVariable()));
+ auto const &last_layer_node = getSortedLayerNode(graph.size() - 1);
+ for (unsigned int i = 0; i < last_layer_node->getNumOutputs(); ++i) {
+ out.push_back(MAKE_SHARED_TENSOR(last_layer_node->getOutput(i)));
+ }
return out;
}
*/
unsigned int getNumOutputs() const { return output_layers.size(); }
+ /**
+ * @brief Get the number of weights
+ *
+ * @return unsigned int number of weights
+ */
+ unsigned int getNumWeights() const {
+ if (LAYER_V2) {
+ return run_context.getNumWeights();
+ } else {
+ return getLayer()->getNumWeights();
+ }
+ }
+
/**
* @brief Get the Input Layers object
*
}
}
+ /**
+ * @brief Get the Weight tensor object
+ *
+ * @param idx Identifier of the weight
+ * @return Tensor& Reference to the weight tensor
+ */
+ Tensor &getWeight(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getWeight(idx);
+ } else {
+ return getLayer()->getWeightsRef()[idx].getVariableRef();
+ }
+ }
+
+ /**
+ * @brief Get the Weight Gradient tensor object
+ *
+ * @param idx Identifier of the weight
+ * @return Tensor& Reference to the weight grad tensor
+ */
+ Tensor &getWeightGrad(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getWeightGrad(idx);
+ } else {
+ return getLayer()->getWeightsRef()[idx].getGradientRef();
+ }
+ }
+
+ /**
+ * @brief Get the Input tensor object
+ *
+ * @param idx Identifier of the input
+ * @return Tensor& Reference to the input grad tensor
+ */
+ Tensor &getInput(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getInput(idx);
+ } else {
+ return getLayer()->getInputRef()[idx]->getVariableRef();
+ }
+ }
+
+ /**
+ * @brief Get the Input Grad tensor object
+ *
+ * @param idx Identifier of the input
+ * @return Tensor& Reference to the input grad tensor
+ */
+ Tensor &getInputGrad(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getInputGrad(idx);
+ } else {
+ return getLayer()->getInputRef()[idx]->getGradientRef();
+ }
+ }
+
+ /**
+ * @brief Get the Output tensor object
+ *
+ * @param idx Identifier of the output
+ * @return Tensor& Reference to the output tensor
+ */
+ Tensor &getOutput(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getOutput(idx);
+ } else {
+ return getLayer()->getOutputRef()[idx]->getVariableRef();
+ }
+ }
+
+ /**
+ * @brief Get the Output Grad tensor object
+ *
+ * @param idx Identifier of the output
+ * @return Tensor& Reference to the output grad tensor
+ */
+ Tensor &getOutputGrad(unsigned int idx) {
+ if (LAYER_V2) {
+ return run_context.getOutputGrad(idx);
+ } else {
+ return getLayer()->getOutputRef()[idx]->getGradientRef();
+ }
+ }
+
/**
* @brief this function helps exporting the layer in a predefined format,
* while workarounding issue caused by templated function type eraser
<< " input_batch: " << input[0]->batch()
<< " label_batch: " << label[0]->batch() << " target_batch: " << batch_size;
- auto fill_label = [&label](auto &layer) {
- NNTR_THROW_IF(label.size() != layer.net_hidden.size(),
+ auto fill_label = [&label](auto const &layer_node) {
+ NNTR_THROW_IF(label.size() != layer_node->getNumOutputs(),
std::invalid_argument)
<< "label size does not match with the layer requirements"
- // TODO: update this to use layer node after #986
- // << " layer: " << layer.getName() << " label size: " << label.size()
- << " layer: "
- << " label size: " << label.size()
- << " requirements size: " << layer.net_hidden.size();
-
- for (unsigned int i = 0; i < layer.net_hidden.size(); i++) {
- layer.net_hidden[i]->getGradientRef() = *label[i];
+ << " layer: " << layer_node->getName() << " label size: " << label.size()
+ << " requirements size: " << layer_node->getNumOutputs();
+
+ for (unsigned int i = 0; i < layer_node->getNumOutputs(); i++) {
+ layer_node->getOutputGrad(i) = *label[i];
}
};
- auto clear_label = [](auto &layer) {
- for (unsigned int i = 0; i < layer.net_hidden.size(); i++) {
- layer.net_hidden[i]->getGradientRef() = Tensor();
+ auto clear_label = [](auto const &layer_node) {
+ for (unsigned int i = 0; i < layer_node->getNumOutputs(); i++) {
+ layer_node->getOutputGrad(i) = Tensor();
}
};
for (auto iter = model_graph.cbegin(); iter != model_graph.cend(); iter++) {
auto &l = *iter->getObject();
if (l.requireLabel()) {
- label.empty() ? clear_label(l) : fill_label(l);
+ label.empty() ? clear_label(*iter) : fill_label(*iter);
}
}
- auto &first_layer = model_graph.getSortedLayerNode(0)->getObject();
- first_layer->net_input[0]->getVariableRef() = *input[0];
+ model_graph.getSortedLayerNode(0)->getInput(0) = *input[0].get();
return forwarding(training);
}
* No need to call at first Input Layer (No data to be updated)
*/
void NeuralNetwork::backwarding(sharedConstTensors label, int iteration) {
- auto &loss_layer =
- model_graph.getSortedLayerNode(model_graph.size() - 1)->getObject();
- loss_layer->net_hidden[0]->getGradientRef() = *label[0].get();
+ auto const &loss_layer_node =
+ model_graph.getSortedLayerNode(model_graph.size() - 1);
+ loss_layer_node->getOutputGrad(0) = *label[0].get();
backwarding(iteration);
}
forwarding(X, {}, false);
END_PROFILE(profile::NN_FORWARD);
- auto &last_layer =
- model_graph.getSortedLayerNode(model_graph.size() - 1)->getObject();
- for (unsigned int i = 0; i < last_layer->getNumOutputs(); ++i) {
- out.push_back(MAKE_SHARED_TENSOR(last_layer->net_hidden[i]->getVariable()));
+ auto const &last_layer_node =
+ model_graph.getSortedLayerNode(model_graph.size() - 1);
+ for (unsigned int i = 0; i < last_layer_node->getNumOutputs(); ++i) {
+ out.push_back(MAKE_SHARED_TENSOR(last_layer_node->getOutput(i)));
}
if (free_mem)
iter = 0;
}
- auto &first_layer = model_graph.getSortedLayerNode(0)->getObject();
- auto &last_layer =
- model_graph.getSortedLayerNode(model_graph.size() - 1)->getObject();
+ auto const &first_layer_node = model_graph.getSortedLayerNode(0);
+ auto const &last_layer_node =
+ model_graph.getSortedLayerNode(model_graph.size() - 1);
- auto &output = last_layer->net_hidden[0]->getVariableRef();
- auto &label = last_layer->net_hidden[0]->getGradientRef();
- auto &in = first_layer->net_input[0]->getVariableRef();
+ auto &output = last_layer_node->getOutput(0);
+ auto &label = last_layer_node->getOutputGrad(0);
+ auto &in = first_layer_node->getInput(0);
for (epoch_idx = epoch_idx + 1; epoch_idx <= epochs; ++epoch_idx) {
training.loss = 0.0f;
* Watcher Classes *
********************************************************/
-using NodeType = std::shared_ptr<const nntrainer::LayerNode>;
+using NodeType = std::shared_ptr<nntrainer::LayerNode>;
using FlatGraphType = nntrainer::NeuralNetwork::FlatGraphType;
using NetworkGraphType = nntrainer::NetworkGraph;
* @param node node to watch.
*/
NodeWatcher(const NodeType &node) : node(node) {
- unsigned int num_weights = node->getObject()->getNumWeights();
+ unsigned int num_weights = node->getNumWeights();
try {
node->getObject()->setTrainable(true);
} catch (...) {
*
*/
void readLayerWeight(std::ifstream &f) {
- for (unsigned int i = 0; i < node->getObject()->getNumWeights(); ++i) {
+ for (unsigned int i = 0; i < node->getNumWeights(); ++i) {
/// @note below is harrasing the fact the tensor shares same base memory
- node->getObject()->weightAt(i).getVariable().read(f);
+ node->getWeight(i).read(f);
}
}
void NodeWatcher::verifyWeight(const std::string &error_msg) {
for (unsigned int i = 0; i < expected_weights.size(); ++i) {
- verify(node->getObject()->weightAt(i).getVariable(),
- expected_weights[i].getVariable(),
+ verify(node->getWeight(i), expected_weights[i].getVariable(),
error_msg + " " + node->getObject()->weightAt(i).getName() +
" weight");
}