Line data Source code
1 : // SPDX-License-Identifier: Apache-2.0
2 : /**
3 : * Copyright (C) 2021 Parichay Kapoor <pk.kapoor@samsung.com>
4 : *
5 : * @file cross_entropy_Softmax_loss_layer.cpp
6 : * @date 24 June 2021
7 : * @brief This is MSE Loss Layer Class of Neural Network
8 : * @see https://github.com/nnstreamer/nntrainer
9 : * @author Parichay Kapoor <pk.kapoor@samsung.com>
10 : * @bug No known bugs except for NYI items
11 : *
12 : */
13 :
14 : #include <cmath>
15 :
16 : #include <cross_entropy_softmax_loss_layer.h>
17 :
18 : #include <acti_func.h>
19 : #include <layer_context.h>
20 : #include <lazy_tensor.h>
21 : #include <util_func.h>
22 :
23 : namespace nntrainer {
24 :
25 : static constexpr size_t SINGLE_INOUT_IDX = 0;
26 :
27 535 : void CrossEntropySoftmaxLossLayer::forwarding(RunLayerContext &context,
28 : bool training) {
29 535 : Tensor &hidden_ = context.getOutput(SINGLE_INOUT_IDX);
30 535 : Tensor &y = context.getInput(SINGLE_INOUT_IDX);
31 :
32 : // fill the output
33 535 : auto dataType = y.getDataType();
34 535 : if (dataType == ml::train::TensorDim::DataType::FP32) {
35 535 : hidden_ = y.apply(ActiFunc::softmax<float>, hidden_);
36 :
37 535 : if (context.isLabelAvailable(SINGLE_INOUT_IDX)) {
38 442 : Tensor &y2 = context.getLabel(SINGLE_INOUT_IDX);
39 884 : l = y2.multiply(hidden_.apply<float>(logFloat<float>))
40 442 : .sum_by_batch()
41 884 : .multiply(-1.0f);
42 :
43 : // update the loss value
44 442 : LossLayer::updateLoss(context, l);
45 : }
46 0 : } else if (dataType == ml::train::TensorDim::DataType::FP16) {
47 : #ifdef ENABLE_FP16
48 : hidden_ = y.apply(ActiFunc::softmax<_FP16>, hidden_);
49 :
50 : if (context.isLabelAvailable(SINGLE_INOUT_IDX)) {
51 : Tensor &y2 = context.getLabel(SINGLE_INOUT_IDX);
52 : l = y2.multiply(hidden_.apply<_FP16>(logFloat<_FP16>))
53 : .sum_by_batch()
54 : .multiply(-1);
55 :
56 : // update the loss value
57 : LossLayer::updateLoss(context, l);
58 : }
59 : #else
60 0 : throw std::invalid_argument("Error: enable-fp16 is not enabled");
61 : #endif
62 : }
63 535 : }
64 :
65 344 : void CrossEntropySoftmaxLossLayer::calcDerivative(RunLayerContext &context) {
66 344 : Tensor &ret_derivative = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
67 344 : const Tensor &y2 = context.getIncomingDerivative(SINGLE_INOUT_IDX);
68 344 : Tensor &y = context.getInput(SINGLE_INOUT_IDX);
69 :
70 344 : auto dataType = y.getDataType();
71 344 : Tensor ret = Tensor("ret", y.getFormat(), y.getDataType());
72 344 : if (dataType == ml::train::TensorDim::DataType::FP32) {
73 688 : y.apply(ActiFunc::softmax<float>, ret);
74 0 : } else if (dataType == ml::train::TensorDim::DataType::FP16) {
75 : #ifdef ENABLE_FP16
76 : y.apply(ActiFunc::softmax<_FP16>, ret);
77 : #else
78 0 : throw std::runtime_error("enable-fp16 is not enabled");
79 : #endif
80 : }
81 :
82 : /// @note y and ret_derivative can be same here, so this has to be out-place
83 : /// operation
84 : // TODO: verify y and ret_derivative must not be same as loss layer is not
85 : // working in-place
86 344 : ret.subtract(y2, ret_derivative);
87 344 : if (ret_derivative.divide_i(ret.batch()) != ML_ERROR_NONE) {
88 : throw std::runtime_error("[CrossEntropySoftmaxLossLayer::calcDerivative] "
89 0 : "Error when calculating loss");
90 : }
91 344 : }
92 :
93 : } // namespace nntrainer
|