Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * Copyright (C) 2025 SeungBaek Hong <sb92.hong@samsung.com>
4 : *
5 : * @file slice_layer.cpp
6 : * @date 02 April 2025
7 : * @see https://github.com/nnstreamer/nntrainer
8 : * @author SeungBaek Hong <sb92.hong@samsung.com>
9 : * @bug No known bugs except for NYI items
10 : * @brief This is slice layer class (operation layer)
11 : */
12 :
13 : #include "common_properties.h"
14 : #include "tensor_base.h"
15 : #include <nntrainer_error.h>
16 : #include <nntrainer_log.h>
17 : #include <node_exporter.h>
18 : #include <slice_layer.h>
19 : #include <stdexcept>
20 : #include <util_func.h>
21 :
22 : #include <layer_context.h>
23 :
24 : namespace nntrainer {
25 :
26 0 : void SliceLayer::finalize(InitLayerContext &context) {
27 0 : axis = std::get<props::Axis>(slice_props).get();
28 0 : start = std::get<props::StartIndex>(slice_props).get() - 1;
29 0 : unsigned int end = std::get<props::EndIndex>(slice_props).get() - 1;
30 :
31 : const TensorDim &in_dim = context.getInputDimensions()[0];
32 0 : TensorDim outputDim = context.getInputDimensions()[0];
33 :
34 0 : for (unsigned int i = 0; i < 4; ++i) {
35 0 : if (i == axis) {
36 0 : outputDim[i] = end - start;
37 : } else {
38 0 : outputDim[i] = in_dim[i];
39 : }
40 : }
41 :
42 0 : context.setOutputDimensions({outputDim});
43 0 : }
44 :
45 0 : void SliceLayer::forwarding_operation(const Tensor &input, Tensor &output) {
46 0 : TensorDim outputDim = output.getDim();
47 :
48 0 : for (unsigned int b = 0; b < output.batch(); ++b) {
49 0 : for (unsigned int c = 0; c < output.channel(); ++c) {
50 0 : for (unsigned int h = 0; h < output.height(); ++h) {
51 0 : for (unsigned int w = 0; w < output.width(); ++w) {
52 0 : unsigned int c_idx = (axis == 1) ? c + start : c;
53 0 : unsigned int h_idx = (axis == 2) ? h + start : h;
54 0 : unsigned int w_idx = (axis == 3) ? w + start : w;
55 0 : output.setValue(b, c, h, w, input.getValue(b, c_idx, h_idx, w_idx));
56 : }
57 : }
58 : }
59 : }
60 0 : }
61 :
62 0 : void SliceLayer::calcDerivative(RunLayerContext &context) {
63 0 : const Tensor &inDeriv = context.getIncomingDerivative(SINGLE_INOUT_IDX);
64 0 : Tensor &outDeriv = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
65 :
66 0 : for (unsigned int b = 0; b < inDeriv.batch(); ++b) {
67 0 : for (unsigned int c = 0; c < inDeriv.channel(); ++c) {
68 0 : for (unsigned int h = 0; h < inDeriv.height(); ++h) {
69 0 : for (unsigned int w = 0; w < inDeriv.width(); ++w) {
70 0 : unsigned int c_idx = (axis == 1) ? c + start : c;
71 0 : unsigned int h_idx = (axis == 2) ? h + start : h;
72 0 : unsigned int w_idx = (axis == 3) ? w + start : w;
73 0 : outDeriv.setValue(b, c_idx, h_idx, w_idx,
74 0 : inDeriv.getValue(b, c, h, w));
75 : }
76 : }
77 : }
78 : }
79 0 : }
80 :
81 0 : void SliceLayer::setProperty(const std::vector<std::string> &values) {
82 0 : auto remain_props = loadProperties(values, slice_props);
83 0 : if (!remain_props.empty()) {
84 : std::string msg = "[SliceLayer] Unknown Layer Properties count " +
85 0 : std::to_string(values.size());
86 0 : throw exception::not_supported(msg);
87 : }
88 0 : }
89 :
90 : } /* namespace nntrainer */
|