// // Copyright © 2017-2024 Arm Ltd and Contributors. All rights reserved. // SPDX-License-Identifier: MIT // #include "MeanLayer.hpp" #include "LayerCloneBase.hpp" #include #include #include #include #include namespace armnn { MeanLayer::MeanLayer(const armnn::MeanDescriptor& param, const char* name) : LayerWithParameters(1, 1, LayerType::Mean, param, name) {} std::unique_ptr MeanLayer::CreateWorkload(const armnn::IWorkloadFactory& factory) const { MeanQueueDescriptor descriptor; descriptor.m_Parameters.m_Axis = m_Param.m_Axis; descriptor.m_Parameters.m_KeepDims = m_Param.m_KeepDims; SetAdditionalInfo(descriptor); return factory.CreateWorkload(LayerType::Mean, descriptor, PrepInfoAndDesc(descriptor)); } MeanLayer* MeanLayer::Clone(Graph& graph) const { auto layer = CloneBase(graph, m_Param, GetName()); layer->m_Param.m_Axis = m_Param.m_Axis; layer->m_Param.m_KeepDims = m_Param.m_KeepDims; return std::move(layer); } void MeanLayer::ValidateTensorShapesFromInputs() { VerifyLayerConnections(1, CHECK_LOCATION()); const TensorShape& outputShape = GetOutputSlot(0).GetTensorInfo().GetShape(); VerifyShapeInferenceType(outputShape, m_ShapeInferenceMethod); std::vector inferredShapes = InferOutputShapes( { GetInputSlot(0).GetTensorInfo().GetShape() }); if (inferredShapes.size() != 1) { throw armnn::LayerValidationException("inferredShapes has " + std::to_string(inferredShapes.size()) + " elements - should only have 1."); } if (inferredShapes[0].GetDimensionality() != Dimensionality::Specified) { throw armnn::LayerValidationException("inferredShapes' dimensionality has not been specified."); } ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "MeanLayer"); } std::vector MeanLayer::InferOutputShapes(const std::vector& inputShapes) const { if (inputShapes.size() != 1) { throw armnn::Exception("inputShapes' size is \"" + std::to_string(inputShapes.size()) + "\" - should be \"1\"."); } const TensorShape& input = inputShapes[0]; auto inputDims = input.GetNumDimensions(); if (inputDims < 1 || inputDims > 4) { throw armnn::Exception("ReduceLayer: Reduce supports up to 4D input."); } unsigned int rank = input.GetNumDimensions(); unsigned int outputRank = 0; // Calculate output dimension if (m_Param.m_KeepDims) { outputRank = rank; } else if (m_Param.m_Axis.empty()) { outputRank = 1; } else if (m_Param.m_Axis.size() > input.GetNumDimensions()) { throw LayerValidationException("MeanLayer: Dimensions to reduce can not be bigger than input dimensions"); } else { outputRank = input.GetNumDimensions() - armnn::numeric_cast(m_Param.m_Axis.size()); if (outputRank == 0) { outputRank = 1; } } std::vector dimSizes(outputRank, 1); if (!m_Param.m_Axis.empty()) { // Skip the dimension that has been reduced unless keepDims is true. unsigned int outputIndex = 0; for (unsigned int i = 0; i < input.GetNumDimensions(); ++i) { if (std::find(m_Param.m_Axis.begin(), m_Param.m_Axis.end(), i) == m_Param.m_Axis.end()) { dimSizes[outputIndex] = armnn::numeric_cast(input[i]); ++outputIndex; } else if (m_Param.m_KeepDims) { dimSizes[outputIndex] = 1; ++outputIndex; } } } return std::vector({ TensorShape(outputRank, dimSizes.data()) }); } void MeanLayer::ExecuteStrategy(IStrategy& strategy) const { strategy.ExecuteStrategy(this, GetParameters(), {}, GetName()); } } // namespace armnn