Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * Copyright (C) 2020 Jijoong Moon <jijoong.moon@samsung.com>
4 : *
5 : * @file multiout_layer.cpp
6 : * @date 05 Nov 2020
7 : * @see https://github.com/nnstreamer/nntrainer
8 : * @author Jijoong Moon <jijoong.moon@samsung.com>
9 : * @bug No known bugs except for NYI items
10 : * @brief This is Multi Output Layer Class for Neural Network
11 : *
12 : */
13 :
14 : #include <cstring>
15 : #include <layer_context.h>
16 : #include <multiout_layer.h>
17 : #include <nntrainer_error.h>
18 : #include <nntrainer_log.h>
19 : #include <util_func.h>
20 :
21 : namespace nntrainer {
22 :
23 : static constexpr size_t SINGLE_INOUT_IDX = 0;
24 :
25 388 : void MultiOutLayer::finalize(InitLayerContext &context) {
26 388 : std::vector<TensorDim> out_dims(context.getNumRequestedOutputs());
27 : const TensorDim &in_dim = context.getInputDimensions()[0];
28 :
29 : std::fill(out_dims.begin(), out_dims.end(), in_dim);
30 388 : context.setOutputDimensions(out_dims);
31 388 : }
32 :
33 571 : void MultiOutLayer::forwarding(RunLayerContext &context, bool training) {
34 571 : if (!context.getInPlace()) {
35 563 : const Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
36 2012 : for (unsigned int idx = 0; idx < context.getNumOutputs(); ++idx) {
37 1449 : context.getOutput(idx).fill(input_);
38 : }
39 : }
40 571 : }
41 :
42 0 : void MultiOutLayer::incremental_forwarding(RunLayerContext &context,
43 : unsigned int from, unsigned int to,
44 : bool training) {
45 0 : if (!context.getInPlace()) {
46 0 : if (from) {
47 0 : NNTR_THROW_IF(to - from != 1, std::invalid_argument)
48 : << "incremental step size is not 1";
49 : from = 0;
50 : to = 1;
51 : }
52 :
53 0 : const Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
54 0 : TensorDim input_dim = input_.getDim();
55 0 : TensorDim input_step_dim = {input_dim.batch(), input_dim.channel(),
56 0 : to - from, input_dim.width()};
57 0 : Tensor input_step = input_.getSharedDataTensor(input_step_dim, 0, true);
58 :
59 0 : for (unsigned int idx = 0; idx < context.getNumOutputs(); ++idx) {
60 0 : Tensor &output = context.getOutput(idx);
61 :
62 0 : TensorDim output_dim = output.getDim();
63 0 : TensorDim output_step_dim = {output_dim.batch(), output_dim.channel(),
64 0 : to - from, output_dim.width()};
65 : // @todo: set reset stride as false. This implementation only works when
66 : // batch size is 1
67 0 : Tensor output_step = output.getSharedDataTensor(output_step_dim, 0, true);
68 0 : output_step.fill(input_step);
69 0 : }
70 0 : }
71 0 : }
72 :
73 220 : void MultiOutLayer::calcDerivative(RunLayerContext &context) {
74 220 : Tensor &ret = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
75 754 : for (unsigned int idx = 0; idx < context.getNumOutputs(); ++idx) {
76 534 : if (idx == 0) {
77 220 : ret.copy(context.getIncomingDerivative(idx));
78 : } else {
79 314 : ret.add_i(context.getIncomingDerivative(idx));
80 : }
81 : }
82 220 : }
83 :
84 2067 : void MultiOutLayer::setProperty(const std::vector<std::string> &values) {
85 2067 : if (!values.empty()) {
86 : std::string msg = "[MultioutLayer] Unknown Layer Properties count " +
87 3 : std::to_string(values.size());
88 6 : throw exception::not_supported(msg);
89 : }
90 2064 : }
91 :
92 0 : void MultiOutLayer::updateTensorsByInputDimensions(
93 : nntrainer::RunLayerContext &context,
94 : std::vector<nntrainer::TensorDim> input_dimensions) {
95 0 : context.updateInput(SINGLE_INOUT_IDX, input_dimensions[0]);
96 :
97 0 : for (size_t i = 0; i < context.getNumOutputs(); ++i) {
98 0 : context.updateOutput(i, input_dimensions[0]);
99 : }
100 0 : }
101 :
102 : } /* namespace nntrainer */
|