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 kld_loss_layer.cpp
6 : * @date 25 November 2021
7 : * @brief KLD (Kullback-Leibler Divergence) loss implementation
8 : * @see https://github.com/nnstreamer/nntrainer
9 : * @author Jihoon Lee <jhoon.it.lee@samsung.com>
10 : * @author Donghak Park <donghak.park@samsung.com>
11 : * @bug No known bugs except for NYI items
12 : *
13 : */
14 : #include <kld_loss_layer.h>
15 : #include <layer_context.h>
16 : #include <string>
17 : #include <vector>
18 :
19 : namespace nntrainer {
20 : static constexpr size_t SINGLE_INOUT_IDX = 0;
21 :
22 0 : void KLDLossLayer::forwarding(RunLayerContext &context, bool training) {
23 : // Result = (P * (P / Q).log()).sum()
24 : // KL(P ∣∣ Q) whereP denotes the distribution of the observations in datasets
25 : // and Q denotes the model output.
26 :
27 0 : nntrainer::Tensor &predicted = context.getInput(SINGLE_INOUT_IDX);
28 0 : nntrainer::Tensor &output = context.getOutput(SINGLE_INOUT_IDX);
29 0 : if (context.isLabelAvailable(SINGLE_INOUT_IDX)) {
30 0 : nntrainer::Tensor &label = context.getLabel(SINGLE_INOUT_IDX);
31 0 : nntrainer::Tensor temp; // temp output
32 : /**
33 : * 1. Output = label / predicted
34 : * 2. Output = log(Output)
35 : * 3. Output = Output * label
36 : * 4. Output = sum(output)
37 : */
38 0 : label.divide(predicted, temp);
39 0 : temp.apply<float>(logf, temp);
40 0 : temp.multiply_i(label);
41 0 : output.fill(temp.sum({0, 1, 2, 3}));
42 0 : }
43 0 : }
44 :
45 0 : void KLDLossLayer::calcDerivative(RunLayerContext &context) {
46 : /**
47 : * d/dQ = -P/Q
48 : */
49 0 : nntrainer::Tensor &predicted = context.getInput(SINGLE_INOUT_IDX); // Q
50 0 : nntrainer::Tensor &label = context.getLabel(SINGLE_INOUT_IDX); // P
51 0 : nntrainer::Tensor &deriv = context.getOutgoingDerivative(SINGLE_INOUT_IDX);
52 :
53 0 : label.multiply_i(-1.0f);
54 0 : label.divide(predicted, deriv);
55 0 : }
56 :
57 : } // namespace nntrainer
|