ArmNN
 20.05
QuantizedLstmLayer.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "QuantizedLstmLayer.hpp"
6 
7 #include "LayerCloneBase.hpp"
8 
10 #include <armnn/TypesUtils.hpp>
13 
14 namespace armnn
15 {
16 
18  : Layer(3, 2, LayerType::QuantizedLstm, name)
19 {
20 }
21 
22 std::unique_ptr<IWorkload> QuantizedLstmLayer::CreateWorkload(const IWorkloadFactory& factory) const
23 {
25 
26  // QuantizedLstmLayer parameters - there are no optional params
31 
36 
41 
42  return factory.CreateQuantizedLstm(descriptor, PrepInfoAndDesc(descriptor));
43 }
44 
46 {
47  auto layer = CloneBase<QuantizedLstmLayer>(graph, GetName());
48 
50  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_InputToInputWeights) : nullptr;
51  layer->m_QuantizedLstmParameters.m_InputToForgetWeights = m_QuantizedLstmParameters.m_InputToForgetWeights ?
52  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_InputToForgetWeights) : nullptr;
53  layer->m_QuantizedLstmParameters.m_InputToCellWeights = m_QuantizedLstmParameters.m_InputToCellWeights ?
54  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_InputToCellWeights) : nullptr;
55  layer->m_QuantizedLstmParameters.m_InputToOutputWeights = m_QuantizedLstmParameters.m_InputToOutputWeights ?
56  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_InputToOutputWeights) : nullptr;
57 
58  layer->m_QuantizedLstmParameters.m_RecurrentToInputWeights = m_QuantizedLstmParameters.m_RecurrentToInputWeights ?
59  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_RecurrentToInputWeights) : nullptr;
60  layer->m_QuantizedLstmParameters.m_RecurrentToForgetWeights = m_QuantizedLstmParameters.m_RecurrentToForgetWeights
61  ? std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_RecurrentToForgetWeights) : nullptr;
62  layer->m_QuantizedLstmParameters.m_RecurrentToCellWeights = m_QuantizedLstmParameters.m_RecurrentToCellWeights ?
63  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_RecurrentToCellWeights) : nullptr;
64  layer->m_QuantizedLstmParameters.m_RecurrentToOutputWeights = m_QuantizedLstmParameters.m_RecurrentToOutputWeights
65  ? std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_RecurrentToOutputWeights) : nullptr;
66 
67  layer->m_QuantizedLstmParameters.m_InputGateBias = m_QuantizedLstmParameters.m_InputGateBias ?
68  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_InputGateBias) : nullptr;
69  layer->m_QuantizedLstmParameters.m_ForgetGateBias = m_QuantizedLstmParameters.m_ForgetGateBias ?
70  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_ForgetGateBias) : nullptr;
71  layer->m_QuantizedLstmParameters.m_CellBias = m_QuantizedLstmParameters.m_CellBias ?
72  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_CellBias) : nullptr;
73  layer->m_QuantizedLstmParameters.m_OutputGateBias = m_QuantizedLstmParameters.m_OutputGateBias ?
74  std::make_unique<ScopedCpuTensorHandle>(*m_QuantizedLstmParameters.m_OutputGateBias) : nullptr;
75 
76  return std::move(layer);
77 }
78 
79 std::vector<TensorShape> QuantizedLstmLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
80 {
81  ARMNN_ASSERT(inputShapes.size() == 3);
82 
83  // Get input values for validation
84  unsigned int numBatches = inputShapes[0][0];
85  unsigned int outputSize = inputShapes[1][1];
86 
87  std::vector<TensorShape> outShapes;
88  outShapes.push_back(TensorShape({numBatches, outputSize})); // cellStateOut
89  outShapes.push_back(TensorShape({numBatches, outputSize})); // output
90 
91  return outShapes;
92 }
93 
95 {
97 
98  auto inferredShapes = InferOutputShapes(
99  {
101  GetInputSlot(1).GetConnection()->GetTensorInfo().GetShape(), // previousCellStateIn
102  GetInputSlot(2).GetConnection()->GetTensorInfo().GetShape() // previousOutputIn
103  });
104 
105  ARMNN_ASSERT(inferredShapes.size() == 2);
106 
107  // Check weights and bias for nullptr
109  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_InputToInputWeights should not be null.");
111  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_InputToForgetWeights should not be null.");
113  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_InputToCellWeights should not be null.");
115  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_InputToOutputWeights should not be null.");
116 
118  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_RecurrentToInputWeights should not be null.");
120  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_RecurrentToForgetWeights should not be null.");
122  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_RecurrentToCellWeights should not be null.");
124  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_RecurrentToOutputWeights should not be null.");
125 
127  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_InputGateBias should not be null.");
129  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_ForgetGateBias should not be null.");
131  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_CellBias should not be null.");
133  "QuantizedLstmLayer: m_QuantizedLstmParameters.m_OutputGateBias should not be null.");
134 
135  // Check output TensorShape(s) match inferred shape
136  ConditionalThrowIfNotEqual<LayerValidationException>(
137  "QuantizedLstmLayer: TensorShape set on OutputSlot[0] does not match the inferred shape.",
139  inferredShapes[0]);
140 
141  ConditionalThrowIfNotEqual<LayerValidationException>(
142  "QuantizedLstmLayer: TensorShape set on OutputSlot[1] does not match the inferred shape.",
144  inferredShapes[1]);
145 }
146 
148 {
149  return
150  {
155 
160 
165  };
166 }
167 
169 {
170  QuantizedLstmInputParams inputParams;
171 
172  // InputToX weight tensors
173  ConstTensor inputToInputWeightsTensor;
175  {
176  ConstTensor inputToInputWeightsTensorCopy(m_QuantizedLstmParameters.m_InputToInputWeights->GetTensorInfo(),
178  inputToInputWeightsTensor = inputToInputWeightsTensorCopy;
179  inputParams.m_InputToInputWeights = &inputToInputWeightsTensor;
180  }
181 
182  ConstTensor inputToForgetWeightsTensor;
184  {
185  ConstTensor inputToForgetWeightsTensorCopy(m_QuantizedLstmParameters.m_InputToForgetWeights->GetTensorInfo(),
187  inputToForgetWeightsTensor = inputToForgetWeightsTensorCopy;
188  inputParams.m_InputToForgetWeights = &inputToForgetWeightsTensor;
189  }
190 
191  ConstTensor inputToCellWeightsTensor;
193  {
194  ConstTensor inputToCellWeightsTensorCopy(m_QuantizedLstmParameters.m_InputToCellWeights->GetTensorInfo(),
196  inputToCellWeightsTensor = inputToCellWeightsTensorCopy;
197  inputParams.m_InputToCellWeights = &inputToCellWeightsTensor;
198  }
199 
200  ConstTensor inputToOutputWeightsTensor;
202  {
203  ConstTensor inputToOutputWeightsTensorCopy(m_QuantizedLstmParameters.m_InputToOutputWeights->GetTensorInfo(),
205  inputToOutputWeightsTensor = inputToOutputWeightsTensorCopy;
206  inputParams.m_InputToOutputWeights = &inputToOutputWeightsTensor;
207  }
208 
209  // RecurrentToX weight tensors
210  ConstTensor recurrentToInputWeightsTensor;
212  {
213  ConstTensor recurrentToInputWeightsTensorCopy(
216  recurrentToInputWeightsTensor = recurrentToInputWeightsTensorCopy;
217  inputParams.m_RecurrentToInputWeights = &recurrentToInputWeightsTensor;
218  }
219 
220  ConstTensor recurrentToForgetWeightsTensor;
222  {
223  ConstTensor recurrentToForgetWeightsTensorCopy(
226  recurrentToForgetWeightsTensor = recurrentToForgetWeightsTensorCopy;
227  inputParams.m_RecurrentToForgetWeights = &recurrentToForgetWeightsTensor;
228  }
229 
230  ConstTensor recurrentToCellWeightsTensor;
232  {
233  ConstTensor recurrentToCellWeightsTensorCopy(
236  recurrentToCellWeightsTensor = recurrentToCellWeightsTensorCopy;
237  inputParams.m_RecurrentToCellWeights = &recurrentToCellWeightsTensor;
238  }
239 
240  ConstTensor recurrentToOutputWeightsTensor;
242  {
243  ConstTensor recurrentToOutputWeightsTensorCopy(
246  recurrentToOutputWeightsTensor = recurrentToOutputWeightsTensorCopy;
247  inputParams.m_RecurrentToOutputWeights = &recurrentToOutputWeightsTensor;
248  }
249 
250  // Bias tensors
251  ConstTensor inputGateBiasTensor;
253  {
254  ConstTensor inputGateBiasTensorCopy(m_QuantizedLstmParameters.m_InputGateBias->GetTensorInfo(),
256  inputGateBiasTensor = inputGateBiasTensorCopy;
257  inputParams.m_InputGateBias = &inputGateBiasTensor;
258  }
259 
260  ConstTensor forgetGateBiasTensor;
262  {
263  ConstTensor forgetGateBiasTensorCopy(m_QuantizedLstmParameters.m_ForgetGateBias->GetTensorInfo(),
265  forgetGateBiasTensor = forgetGateBiasTensorCopy;
266  inputParams.m_ForgetGateBias = &forgetGateBiasTensor;
267  }
268 
269  ConstTensor cellBiasTensor;
270  if (m_QuantizedLstmParameters.m_CellBias != nullptr)
271  {
272  ConstTensor cellBiasTensorCopy(m_QuantizedLstmParameters.m_CellBias->GetTensorInfo(),
274  cellBiasTensor = cellBiasTensorCopy;
275  inputParams.m_CellBias = &cellBiasTensor;
276  }
277 
278  ConstTensor outputGateBiasTensor;
280  {
281  ConstTensor outputGateBiasCopy(m_QuantizedLstmParameters.m_OutputGateBias->GetTensorInfo(),
283  outputGateBiasTensor = outputGateBiasCopy;
284  inputParams.m_OutputGateBias = &outputGateBiasTensor;
285  }
286 
287  visitor.VisitQuantizedLstmLayer(this, inputParams, GetName());
288 }
289 
290 } // namespace armnn
const ConstCpuTensorHandle * m_RecurrentToForgetWeights
std::unique_ptr< ScopedCpuTensorHandle > m_RecurrentToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, outputSize] (QAsymm8)...
Layer::ConstantTensors GetConstantTensorsByRef() override
Retrieve the handles to the constant values stored by the layer.
const ConstCpuTensorHandle * m_InputGateBias
QuantizedLstmParameters m_QuantizedLstmParameters
const TensorShape & GetShape() const
Definition: Tensor.hpp:88
std::unique_ptr< ScopedCpuTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8)...
const ConstTensor * m_RecurrentToOutputWeights
std::unique_ptr< ScopedCpuTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, outputSize] (QAsymm8)...
const ConstTensor * m_RecurrentToForgetWeights
QuantizedLstmLayer * Clone(Graph &graph) const override
Creates a dynamically-allocated copy of this layer.
const ConstCpuTensorHandle * m_InputToCellWeights
virtual std::unique_ptr< IWorkload > CreateQuantizedLstm(const QuantizedLstmQueueDescriptor &descriptor, const WorkloadInfo &info) const
std::unique_ptr< ScopedCpuTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8)...
std::unique_ptr< ScopedCpuTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, outputSize] (QAsymm8)...
void ValidateTensorShapesFromInputs() override
Check if the input tensor shape(s) will lead to a valid configuration of QuantizedLstmLayer.
Copyright (c) 2020 ARM Limited.
const IOutputSlot * GetConnection() const override
Definition: Layer.hpp:199
QuantizedLstmLayer(const char *name)
Constructor to create a QuantizedLstmLayer.
std::unique_ptr< ScopedCpuTensorHandle > m_InputGateBias
A unique pointer to represent 1D bias tensor with dimensions [outputSize] (int32).
std::unique_ptr< ScopedCpuTensorHandle > m_CellBias
A unique pointer to represent 1D bias tensor with dimensions [outputSize] (int32).
void VerifyLayerConnections(unsigned int expectedConnections, const CheckLocation &location) const
Definition: Layer.cpp:339
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:310
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
This layer represents a QuantizedLstm operation.
WorkloadInfo PrepInfoAndDesc(QueueDescriptor &descriptor) const
Helper function to reduce duplication in *LayerCreateWorkload.
Definition: Layer.hpp:351
std::unique_ptr< ScopedCpuTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D bias tensor with dimensions [outputSize] (int32).
const ConstTensor * m_InputToForgetWeights
const ConstCpuTensorHandle * m_ForgetGateBias
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:199
const ConstCpuTensorHandle * m_RecurrentToInputWeights
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
void Accept(ILayerVisitor &visitor) const override
Apply a visitor to this layer.
const ConstCpuTensorHandle * m_RecurrentToCellWeights
virtual std::unique_ptr< IWorkload > CreateWorkload(const IWorkloadFactory &factory) const override
Makes a workload for the QuantizedLstm type.
#define CHECK_LOCATION()
Definition: Exceptions.hpp:192
const ConstCpuTensorHandle * m_RecurrentToOutputWeights
const ConstTensor * m_RecurrentToInputWeights
virtual void VisitQuantizedLstmLayer(const IConnectableLayer *layer, const QuantizedLstmInputParams &params, const char *name=nullptr)=0
Function a QuantizedLstm layer should call back to when its Accept(ILayerVisitor&) function is invoke...
std::unique_ptr< ScopedCpuTensorHandle > m_OutputGateBias
A unique pointer to represent 1D bias tensor with dimensions [outputSize] (int32).
const ConstCpuTensorHandle * m_CellBias
const ConstTensor * m_RecurrentToCellWeights
const ConstCpuTensorHandle * m_OutputGateBias
const ConstTensor * m_InputToOutputWeights
std::unique_ptr< ScopedCpuTensorHandle > m_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8)...
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:312
virtual const TensorInfo & GetTensorInfo() const =0
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:305
const ConstCpuTensorHandle * m_InputToForgetWeights
std::unique_ptr< ScopedCpuTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, inputSize] (QAsymm8)...
const ConstCpuTensorHandle * m_InputToOutputWeights
std::vector< std::reference_wrapper< std::unique_ptr< ScopedCpuTensorHandle > >> ConstantTensors
Definition: Layer.hpp:363
const ConstCpuTensorHandle * m_InputToInputWeights
std::unique_ptr< ScopedCpuTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [outputSize, outputSize] (QAsymm8)...
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:63
std::vector< TensorShape > InferOutputShapes(const std::vector< TensorShape > &inputShapes) const override
By default returns inputShapes if the number of inputs are equal to number of outputs, otherwise infers the output shapes from given input shapes and layer properties.