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 dropout_layer.cpp
6 : * @date 16 June 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 Dropout Layer Class for Neural Network
11 : *
12 : */
13 :
14 : #include <dropout.h>
15 : #include <layer_context.h>
16 : #include <nntrainer_error.h>
17 : #include <nntrainer_log.h>
18 : #include <node_exporter.h>
19 : #include <util_func.h>
20 :
21 : namespace nntrainer {
22 :
23 : static constexpr size_t SINGLE_INOUT_IDX = 0;
24 :
25 9 : void DropOutLayer::finalize(InitLayerContext &context) {
26 : auto const &input_dims = context.getInputDimensions();
27 9 : context.setOutputDimensions(input_dims);
28 :
29 9 : mask_idx.reserve(input_dims.size());
30 18 : for (auto &t : input_dims) {
31 18 : mask_idx.push_back(context.requestTensor(
32 : t, "Mask", Initializer::NONE, false, TensorLifespan::ITERATION_LIFESPAN));
33 : }
34 9 : }
35 :
36 21 : void DropOutLayer::forwarding(RunLayerContext &context, bool training) {
37 21 : auto &rate_ = std::get<props::DropOutRate>(dropout_rate).get();
38 :
39 : // Assume it is in-place calculation. It means input and output share mem
40 : // buffer. So if the training is false, the output is the same with input. In
41 : // other words, there is nothing happen during inference.
42 :
43 42 : for (unsigned int i = 0; i < context.getNumInputs(); ++i) {
44 21 : Tensor &input_ = context.getInput(i);
45 21 : Tensor &output_ = context.getOutput(i);
46 :
47 : /** @todo make this in-place */
48 21 : if (training && rate_ > epsilon) {
49 10 : Tensor &mask_ = context.getTensor(mask_idx[i]);
50 10 : if (!context.reStoreData()) {
51 10 : mask_.dropout_mask(rate_);
52 : }
53 :
54 10 : input_.multiply(mask_, output_);
55 10 : } else {
56 11 : output_.fill(input_);
57 : }
58 : }
59 21 : }
60 :
61 3 : void DropOutLayer::calcDerivative(RunLayerContext &context) {
62 : // Assume it is in-place calculation
63 3 : auto &rate_ = std::get<props::DropOutRate>(dropout_rate).get();
64 :
65 6 : for (unsigned int i = 0; i < context.getNumInputs(); ++i) {
66 3 : const Tensor &derivative_ = context.getIncomingDerivative(i);
67 3 : Tensor &ret_ = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
68 :
69 : /** @todo make this in-place */
70 3 : if (rate_ > epsilon) {
71 2 : Tensor &mask_ = context.getTensor(mask_idx[i]);
72 2 : derivative_.multiply(mask_, ret_);
73 : } else {
74 1 : ret_.fill(derivative_);
75 : }
76 3 : }
77 3 : }
78 :
79 43 : void DropOutLayer::setProperty(const std::vector<std::string> &values) {
80 43 : auto remain_props = loadProperties(values, dropout_rate);
81 42 : if (!remain_props.empty()) {
82 : std::string msg = "[DropOutLayer] Unknown Layer Properties count " +
83 2 : std::to_string(values.size());
84 4 : throw exception::not_supported(msg);
85 : }
86 42 : }
87 :
88 : } /* namespace nntrainer */
|