Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * Copyright (C) 2021 Jihoon Lee <jhoon.it.lee@samsung.com>
4 : *
5 : * @file permute_layer.cpp
6 : * @date 06 May 2021
7 : * @brief Permute layer to support transpose
8 : * @see https://github.com/nnstreamer/nntrainer
9 : * @author Jihoon Lee <jhoon.it.lee@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : */
12 : #include <sstream>
13 : #include <string>
14 : #include <tuple>
15 :
16 : #include <layer_context.h>
17 : #include <nntrainer_error.h>
18 : #include <nntrainer_log.h>
19 : #include <node_exporter.h>
20 : #include <permute_layer.h>
21 : #include <tensor.h>
22 : #include <tensor_dim.h>
23 :
24 : namespace nntrainer {
25 :
26 : static constexpr size_t SINGLE_INOUT_IDX = 0;
27 :
28 30 : bool props::PermuteDims::isValid(const unsigned int &value) const {
29 30 : return 0 < value && value <= 3;
30 : }
31 :
32 : /**
33 : * @brief buildTransposeString based on array
34 : * @todo deprecate this
35 : *
36 : * @param arr array to make a representation
37 : * @return const std::string string to return
38 : */
39 : static std::string
40 8 : buildTrasposeString(const std::array<props::PermuteDims, 3> &arr) {
41 8 : std::stringstream ss;
42 8 : ss << arr[0].get() - 1 << ':' << arr[1].get() - 1 << ':' << arr[2].get() - 1;
43 8 : return ss.str();
44 8 : }
45 :
46 4 : void PermuteLayer::finalize(InitLayerContext &context) {
47 4 : auto initiate_direction = [this] {
48 4 : std::bitset<3> check_transpose; /**< check if transpose contains all axis */
49 :
50 16 : for (int i = 0; i < 3; ++i) {
51 12 : check_transpose.set(direction[i] - 1, true);
52 12 : this->reverse_direction[direction[i] - 1].set(i + 1);
53 : }
54 :
55 4 : NNTR_THROW_IF(check_transpose.all() == false, std::invalid_argument)
56 : << "[Permute] "
57 : << "transpose direction is invalid, checked direction: "
58 0 : << check_transpose.to_string();
59 :
60 : /*** @todo deprecate this */
61 4 : direction_str = buildTrasposeString(direction);
62 4 : rdirection_str = buildTrasposeString(reverse_direction);
63 4 : };
64 :
65 4 : initiate_direction();
66 4 : context.setOutputDimensions(
67 4 : {context.getInputDimensions()[SINGLE_INOUT_IDX].transpose(direction_str)});
68 4 : }
69 :
70 0 : void PermuteLayer::forwarding(RunLayerContext &context, bool training) {
71 0 : Tensor &hidden_ = context.getOutput(SINGLE_INOUT_IDX);
72 0 : Tensor &input_ = context.getInput(SINGLE_INOUT_IDX);
73 :
74 0 : input_.transpose(direction_str, hidden_);
75 0 : }
76 :
77 0 : void PermuteLayer::calcDerivative(RunLayerContext &context) {
78 0 : const Tensor &hidden_grad = context.getIncomingDerivative(SINGLE_INOUT_IDX);
79 0 : Tensor &input_grad = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
80 :
81 0 : hidden_grad.transpose(rdirection_str, input_grad);
82 0 : }
83 :
84 0 : void PermuteLayer::exportTo(Exporter &exporter,
85 : const ml::train::ExportMethods &method) const {
86 0 : exporter.saveResult(std::forward_as_tuple(direction), method);
87 0 : }
88 :
89 63 : void PermuteLayer::setProperty(const std::vector<std::string> &values) {
90 63 : auto left_values = loadProperties(values, std::forward_as_tuple(direction));
91 52 : if (!left_values.empty()) {
92 : std::string msg = "[PermuteLayer] Unknown properties set with count" +
93 2 : std::to_string(values.size());
94 4 : throw exception::not_supported(msg);
95 : }
96 52 : }
97 :
98 : } // namespace nntrainer
|