ArmNN
 24.08
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 
13 namespace
14 {
15 
16 inline 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 
24 namespace 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)) :
39  armnn::numeric_cast<unsigned int>(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
armnn::Decoder< float >
armnn::Encoder::Set
virtual void Set(IType right)=0
armnn::SoftmaxDescriptor::m_Beta
float m_Beta
Exponentiation value.
Definition: Descriptors.hpp:190
armnn::TensorInfo
Definition: Tensor.hpp:152
armnn::TensorInfo::GetNumDimensions
unsigned int GetNumDimensions() const
Definition: Tensor.hpp:197
armnn::LogSoftmax
void LogSoftmax(Decoder< float > &input, Encoder< float > &output, const TensorInfo &inputInfo, const LogSoftmaxDescriptor &descriptor)
Definition: LogSoftmax.cpp:27
LogSoftmax.hpp
NumericCast.hpp
TensorUtils.hpp
armnn::TensorShape
Definition: Tensor.hpp:20
armnn::Encoder< float >
armnn::TensorShape::GetNumDimensions
unsigned int GetNumDimensions() const
Function that returns the tensor rank.
Definition: Tensor.cpp:174
armnn::Decoder::Get
virtual IType Get() const =0
armnnUtils::GetNumElementsBetween
unsigned int GetNumElementsBetween(const armnn::TensorShape &shape, unsigned int firstAxisInclusive, unsigned int lastAxisExclusive)
Definition: TensorUtils.cpp:209
armnn::TensorInfo::GetShape
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
armnn::SoftmaxDescriptor::m_Axis
int m_Axis
Scalar, defaulted to the last index (-1), specifying the dimension the activation will be performed o...
Definition: Descriptors.hpp:192
armnn
Copyright (c) 2021 ARM Limited and Contributors.
Definition: 01_00_quick_start.dox:6
armnn::SoftmaxDescriptor
A SoftmaxDescriptor for the SoftmaxLayer.
Definition: Descriptors.hpp:177
ARMNN_THROW_INVALIDARG_MSG_IF_FALSE
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
Definition: Exceptions.hpp:210