ArmNN
 25.11
Loading...
Searching...
No Matches
LogSoftmax.cpp
Go to the documentation of this file.
1//
2// Copyright © 2019, 2024 Arm Ltd. All rights reserved.
3// SPDX-License-Identifier: MIT
4//
5
6#include "LogSoftmax.hpp"
7
10
11#include <cmath>
12
13namespace
14{
15
16inline bool ValidateAxis(int axis, unsigned int numDimensions)
17{
18 const int sNumDimensions = armnn::numeric_cast<int>(numDimensions);
19 return axis < sNumDimensions && axis >= -sNumDimensions;
20}
21
22} // anonymous namespace
23
24namespace armnn
25{
26
28 Encoder<float>& output,
29 const TensorInfo& inputInfo,
30 const LogSoftmaxDescriptor& descriptor)
31{
32 const unsigned int numDimensions = inputInfo.GetNumDimensions();
33
34 ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(ValidateAxis(descriptor.m_Axis, numDimensions),
35 "Axis index is not in range [-numDimensions, numDimensions).");
36
37 unsigned int uAxis = descriptor.m_Axis < 0 ?
38 numDimensions - armnn::numeric_cast<unsigned int>(std::abs(descriptor.m_Axis)) :
40
41 const TensorShape& inputShape = inputInfo.GetShape();
42 const unsigned int outerSize = armnnUtils::GetNumElementsBetween(inputShape, 0, uAxis);
43 const unsigned int axisSize = inputShape[uAxis];
44 const unsigned int innerSize = armnnUtils::GetNumElementsBetween(inputShape,
45 uAxis + 1,
46 inputShape.GetNumDimensions());
47
48 for (unsigned int outer = 0; outer < outerSize; ++outer)
49 {
50 for (unsigned int inner = 0; inner < innerSize; ++inner)
51 {
52 // Find max
53 input[outer * axisSize * innerSize + inner];
54 float maxValue = input.Get();
55 for (unsigned int i = 1u; i < axisSize; ++i)
56 {
57 input[(outer * axisSize + i) * innerSize + inner];
58 maxValue = std::max(maxValue, input.Get());
59 }
60
61 // Compute sum
62 float sum = 0.0f;
63 for (unsigned int i = 0u; i < axisSize; ++i)
64 {
65 input[(outer * axisSize + i) * innerSize + inner];
66 sum += std::exp((input.Get() - maxValue) * descriptor.m_Beta);
67 }
68
69 // Compute log sum
70 const float logSum = std::log(sum);
71
72 // Compute result
73 for (unsigned int i = 0u; i < axisSize; ++i)
74 {
75 const unsigned int index = (outer * axisSize + i) * innerSize + inner;
76
77 input [index];
78 output[index];
79
80 output.Set((input.Get() - maxValue) * descriptor.m_Beta - logSum);
81 }
82 }
83 }
84}
85
86} // namespace armnn
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
virtual IType Get() const =0
virtual void Set(IType right)=0
const TensorShape & GetShape() const
Definition Tensor.hpp:193
unsigned int GetNumDimensions() const
Definition Tensor.hpp:197
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition Tensor.cpp:174
Copyright (c) 2021 ARM Limited and Contributors.
std::enable_if_t< std::is_unsigned< Source >::value &&std::is_unsigned< Dest >::value, Dest > numeric_cast(Source source)
SoftmaxDescriptor LogSoftmaxDescriptor
A LogSoftmaxDescriptor for the LogSoftmaxLayer.
unsigned int GetNumElementsBetween(const armnn::TensorShape &shape, unsigned int firstAxisInclusive, unsigned int lastAxisExclusive)
int m_Axis
Scalar, defaulted to the last index (-1), specifying the dimension the activation will be performed o...
float m_Beta
Exponentiation value.