ArmNN
 22.08
LstmLayer.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2017 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
5 #include "LstmLayer.hpp"
6 
7 #include "LayerCloneBase.hpp"
8 
9 #include <armnn/LstmParams.hpp>
10 #include <armnn/TypesUtils.hpp>
13 
14 namespace armnn
15 {
16 
17 LstmLayer::LstmLayer(const LstmDescriptor& param, const char* name)
18  : LayerWithParameters(3, 4, LayerType::Lstm, param, name)
19 {
20 }
21 
22 std::unique_ptr<IWorkload> LstmLayer::CreateWorkload(const IWorkloadFactory& factory) const
23 {
24  LstmQueueDescriptor descriptor;
25 
26  // Basic parameters
34  descriptor.m_CellBias = m_BasicParameters.m_CellBias.get();
36 
37  // Cifg parameters
39  {
43  }
44 
45  // Projection parameters
47  {
50  }
51 
52  // Peephole parameters
54  {
56  {
58  }
61  }
62 
63  // Layer normalisation parameters
65  {
67  {
69  }
73  }
74 
75  SetAdditionalInfo(descriptor);
76 
77  return factory.CreateWorkload(LayerType::Lstm, descriptor, PrepInfoAndDesc(descriptor));
78 }
79 
81 {
82  auto layer = CloneBase<LstmLayer>(graph, m_Param, GetName());
83 
86  : nullptr;
87  layer->m_BasicParameters.m_InputToCellWeights = m_BasicParameters.m_InputToCellWeights ?
89  layer->m_BasicParameters.m_InputToOutputWeights = m_BasicParameters.m_InputToOutputWeights ?
91  layer->m_BasicParameters.m_RecurrentToForgetWeights = m_BasicParameters.m_RecurrentToForgetWeights ?
93  layer->m_BasicParameters.m_RecurrentToCellWeights = m_BasicParameters.m_RecurrentToCellWeights ?
95  layer->m_BasicParameters.m_RecurrentToOutputWeights = m_BasicParameters.m_RecurrentToOutputWeights ?
97  layer->m_BasicParameters.m_ForgetGateBias = m_BasicParameters.m_ForgetGateBias ?
99  layer->m_BasicParameters.m_CellBias = m_BasicParameters.m_CellBias ?
100  m_BasicParameters.m_CellBias : nullptr;
101  layer->m_BasicParameters.m_OutputGateBias = m_BasicParameters.m_OutputGateBias ?
103 
104  if (!m_Param.m_CifgEnabled)
105  {
106  layer->m_CifgParameters.m_InputToInputWeights = m_CifgParameters.m_InputToInputWeights ?
108  layer->m_CifgParameters.m_RecurrentToInputWeights = m_CifgParameters.m_RecurrentToInputWeights ?
110  layer->m_CifgParameters.m_InputGateBias = m_CifgParameters.m_InputGateBias ?
112  }
113 
114  if (m_Param.m_ProjectionEnabled)
115  {
116  layer->m_ProjectionParameters.m_ProjectionWeights = m_ProjectionParameters.m_ProjectionWeights ?
118  layer->m_ProjectionParameters.m_ProjectionBias = m_ProjectionParameters.m_ProjectionBias ?
120  }
121 
122  if (m_Param.m_PeepholeEnabled)
123  {
124  if (!m_Param.m_CifgEnabled)
125  {
126  layer->m_PeepholeParameters.m_CellToInputWeights = m_PeepholeParameters.m_CellToInputWeights ?
128  }
129  layer->m_PeepholeParameters.m_CellToForgetWeights = m_PeepholeParameters.m_CellToForgetWeights ?
131  layer->m_PeepholeParameters.m_CellToOutputWeights = m_PeepholeParameters.m_CellToOutputWeights ?
133  }
134 
135  if (m_Param.m_LayerNormEnabled)
136  {
137  layer->m_LayerNormParameters.m_InputLayerNormWeights = m_LayerNormParameters.m_InputLayerNormWeights ?
139  layer->m_LayerNormParameters.m_ForgetLayerNormWeights = m_LayerNormParameters.m_ForgetLayerNormWeights ?
141  layer->m_LayerNormParameters.m_CellLayerNormWeights = m_LayerNormParameters.m_CellLayerNormWeights ?
143  layer->m_LayerNormParameters.m_OutputLayerNormWeights = m_LayerNormParameters.m_OutputLayerNormWeights ?
145  }
146 
147  return std::move(layer);
148 }
149 
150 std::vector<TensorShape> LstmLayer::InferOutputShapes(const std::vector<TensorShape>& inputShapes) const
151 {
152  ARMNN_ASSERT(inputShapes.size() == 3);
153 
154  // Get input values for validation
155  unsigned int batchSize = inputShapes[0][0];
156  unsigned int outputSize = inputShapes[1][1];
157  unsigned int numUnits = inputShapes[2][1];
158 
159  std::vector<TensorShape> outShapes;
160  outShapes.push_back(TensorShape({batchSize, numUnits * (m_Param.m_CifgEnabled ? 3 : 4)}));
161  outShapes.push_back(TensorShape({batchSize, outputSize}));
162  outShapes.push_back(TensorShape({batchSize, numUnits}));
163  outShapes.push_back(TensorShape({batchSize, outputSize}));
164 
165  return outShapes;
166 }
167 
169 {
171 
172  const TensorShape& outputShape = GetOutputSlot(0).GetTensorInfo().GetShape();
173 
175 
176  auto inferredShapes = InferOutputShapes( {
180  });
181 
182  ARMNN_ASSERT(inferredShapes.size() == 4);
183 
184  // Check if the weights are nullptr
186  "LstmLayer: m_BasicParameters.m_InputToForgetWeights should not be null.");
188  "LstmLayer: m_BasicParameters.m_InputToCellWeights should not be null.");
190  "LstmLayer: m_BasicParameters.m_InputToOutputWeights should not be null.");
192  "LstmLayer: m_BasicParameters.m_RecurrentToForgetWeights should not be null.");
194  "LstmLayer: m_BasicParameters.m_RecurrentToCellWeights should not be null.");
196  "LstmLayer: m_BasicParameters.m_RecurrentToOutputWeights should not be null.");
198  "LstmLayer: m_BasicParameters.m_ForgetGateBias should not be null.");
200  "LstmLayer: m_BasicParameters.m_CellBias should not be null.");
202  "LstmLayer: m_BasicParameters.m_OutputGateBias should not be null.");
203 
204  if (!m_Param.m_CifgEnabled)
205  {
207  "LstmLayer: m_CifgParameters.m_InputToInputWeights should not be null.");
209  "LstmLayer: m_CifgParameters.m_RecurrentToInputWeights should not be null.");
211  "LstmLayer: m_CifgParameters.m_InputGateBias should not be null.");
212 
213  ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "LstmLayer");
214  }
215  else
216  {
218  "LstmLayer: m_CifgParameters.m_InputToInputWeights should not have a value when CIFG is enabled.");
220  "LstmLayer: m_CifgParameters.m_RecurrentToInputWeights should not have a value when CIFG is enabled.");
222  "LstmLayer: m_CifgParameters.m_InputGateBias should not have a value when CIFG is enabled.");
223 
224  ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "LstmLayer");
225  }
226 
228  {
230  "LstmLayer: m_ProjectionParameters.m_ProjectionWeights should not be null.");
231  }
232 
234  {
235  if (!m_Param.m_CifgEnabled)
236  {
238  "LstmLayer: m_PeepholeParameters.m_CellToInputWeights should not be null "
239  "when Peephole is enabled and CIFG is disabled.");
240  }
242  "LstmLayer: m_PeepholeParameters.m_CellToForgetWeights should not be null.");
244  "LstmLayer: m_PeepholeParameters.m_CellToOutputWeights should not be null.");
245  }
246 
248  GetOutputSlot(1).GetTensorInfo().GetShape(), inferredShapes[1], m_ShapeInferenceMethod, "LstmLayer", 1);
250  GetOutputSlot(2).GetTensorInfo().GetShape(), inferredShapes[2], m_ShapeInferenceMethod, "LstmLayer", 2);
252  GetOutputSlot(3).GetTensorInfo().GetShape(), inferredShapes[3], m_ShapeInferenceMethod, "LstmLayer", 3);
253 
255  {
257  {
259  "LstmLayer: m_LayerNormParameters.m_inputLayerNormWeights should not be null.");
260  }
262  "LstmLayer: m_LayerNormParameters.m_forgetLayerNormWeights should not be null.");
264  "LstmLayer: m_LayerNormParameters.m_cellLayerNormWeights should not be null.");
266  "LstmLayer: m_LayerNormParameters.m_outputLayerNormWeights should not be null.");
267  }
268 }
269 
271 {
272  // For API stability DO NOT ALTER order and add new members to the end of vector
282 
283  // Cifg parameters
287 
288  // Projection parameters
291 
292  // Peephole parameters
296 
297  // Layer normalisation parameters
302 }
303 
305 {
306  std::vector<ConstTensor> constTensors;
307 
308  LstmDescriptor descriptor = GetParameters();
309 
319 
320  // Cifg parameters
324 
325  // Projection parameters
328 
329  // Peephole parameters
333 
334  // Layer normalisation parameters
339 
340  // First add mandatory/basic parameters
342  {
343  constTensors.emplace_back(ConstTensor(managedInputToForgetWeights.GetTensorInfo(),
344  managedInputToForgetWeights.Map()));
345  }
347  {
348  constTensors.emplace_back(ConstTensor(managedInputToCellWeights.GetTensorInfo(),
349  managedInputToCellWeights.Map()));
350  }
352  {
353  constTensors.emplace_back(ConstTensor(managedInputToOutputWeights.GetTensorInfo(),
354  managedInputToOutputWeights.Map()));
355  }
357  {
358  constTensors.emplace_back(ConstTensor(
359  managedRecurrentToForgetWeights.GetTensorInfo(),
360  managedRecurrentToForgetWeights.Map()));
361  }
363  {
364  constTensors.emplace_back(ConstTensor(
365  managedRecurrentToCellWeights.GetTensorInfo(),
366  managedRecurrentToCellWeights.Map()));
367  }
369  {
370  constTensors.emplace_back(ConstTensor(
371  managedRecurrentToOutputWeights.GetTensorInfo(),
372  managedRecurrentToOutputWeights.Map()));
373  }
374  if (m_BasicParameters.m_ForgetGateBias != nullptr)
375  {
376  constTensors.emplace_back(ConstTensor(managedForgetGateBias.GetTensorInfo(),
377  managedForgetGateBias.Map()));
378  }
379  if (m_BasicParameters.m_CellBias != nullptr)
380  {
381  constTensors.emplace_back(ConstTensor(managedCellBias.GetTensorInfo(),
382  managedCellBias.Map()));
383  }
384  if (m_BasicParameters.m_OutputGateBias != nullptr)
385  {
386  constTensors.emplace_back(ConstTensor(managedOutputGateBias.GetTensorInfo(),
387  managedOutputGateBias.Map()));
388  }
389 
390  // Add cifg parameters
391  if (!descriptor.m_CifgEnabled)
392  {
394  {
395  constTensors.emplace_back(ConstTensor(managedInputToInputWeights.GetTensorInfo(),
396  managedInputToInputWeights.Map()));
397  }
399  {
400  constTensors.emplace_back(ConstTensor(
401  managedRecurrentToInputWeights.GetTensorInfo(),
402  managedRecurrentToInputWeights.Map()));
403  }
404  if (m_CifgParameters.m_InputGateBias != nullptr)
405  {
406  constTensors.emplace_back(ConstTensor(managedInputGateBias.GetTensorInfo(),
407  managedInputGateBias.Map()));
408  }
409  }
410 
411  // Add peephole parameters
412  if (descriptor.m_PeepholeEnabled)
413  {
414  if (!descriptor.m_CifgEnabled)
415  {
417  {
418  constTensors.emplace_back(ConstTensor(managedCellToInputWeights.GetTensorInfo(),
419  managedCellToInputWeights.Map()));
420  }
421  }
423  {
424  constTensors.emplace_back(ConstTensor(managedCellToForgetWeights.GetTensorInfo(),
425  managedCellToForgetWeights.Map()));
426  }
428  {
429  constTensors.emplace_back(ConstTensor(managedCellToOutputWeights.GetTensorInfo(),
430  managedCellToOutputWeights.Map()));
431  }
432  }
433 
434  // Add projection parameters
435  if (descriptor.m_ProjectionEnabled)
436  {
438  {
439  constTensors.emplace_back(ConstTensor(managedProjectionWeights.GetTensorInfo(),
440  managedProjectionWeights.Map()));
441  }
443  {
444  constTensors.emplace_back(ConstTensor(managedProjectionBias.GetTensorInfo(),
445  managedProjectionBias.Map()));
446  }
447  }
448 
449  // Add norm parameters
450  if (descriptor.m_LayerNormEnabled)
451  {
452  if (!descriptor.m_CifgEnabled)
453  {
455  {
456  constTensors.emplace_back(ConstTensor(managedInputLayerNormWeights.GetTensorInfo(),
457  managedInputLayerNormWeights.Map()));
458  }
459  }
461  {
462  constTensors.emplace_back(ConstTensor(managedForgetLayerNormWeights.GetTensorInfo(),
463  managedForgetLayerNormWeights.Map()));
464  }
466  {
467  constTensors.emplace_back(ConstTensor(managedCellLayerNormWeights.GetTensorInfo(),
468  managedCellLayerNormWeights.Map()));
469  }
471  {
472  constTensors.emplace_back(ConstTensor(managedOutputLayerNormWeights.GetTensorInfo(),
473  managedOutputLayerNormWeights.Map()));
474  }
475  }
476 
477  strategy.ExecuteStrategy(this, GetParameters(), constTensors, GetName());
478 }
479 
480 } // namespace armnn
std::shared_ptr< ConstTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_OutputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
bool m_ProjectionEnabled
Enable/disable the projection layer.
LstmBasicParameters m_BasicParameters
Definition: LstmLayer.hpp:20
const ConstTensorHandle * m_ProjectionWeights
const ConstTensorHandle * m_RecurrentToForgetWeights
std::shared_ptr< ConstTensorHandle > m_OutputLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_CellToForgetWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
LstmDescriptor m_Param
The parameters for the layer (not including tensor-valued weights etc.).
const TensorShape & GetShape() const
Definition: Tensor.hpp:191
const ConstTensorHandle * m_InputGateBias
const ConstTensorHandle * m_RecurrentToCellWeights
const ConstTensorHandle * m_CellBias
std::shared_ptr< ConstTensorHandle > m_InputLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
virtual std::unique_ptr< IWorkload > CreateWorkload(const IWorkloadFactory &factory) const override
Makes a workload for the LSTM type.
Definition: LstmLayer.cpp:22
const ConstTensorHandle * m_InputToOutputWeights
std::shared_ptr< ConstTensorHandle > m_ProjectionWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
const ConstTensorHandle * m_OutputLayerNormWeights
void VerifyShapeInferenceType(const TensorShape &outputShape, ShapeInferenceMethod shapeInferenceMethod)
Definition: Layer.cpp:491
const TensorInfo & GetTensorInfo() const
Copyright (c) 2021 ARM Limited and Contributors.
std::shared_ptr< ConstTensorHandle > m_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
const LstmDescriptor & GetParameters() const override
This layer represents a LSTM operation.
Definition: LstmLayer.hpp:16
const IOutputSlot * GetConnection() const override
Definition: Layer.hpp:206
void ExecuteStrategy(IStrategy &strategy) const override
Apply a visitor to this layer.
Definition: LstmLayer.cpp:304
void ValidateAndCopyShape(const TensorShape &outputShape, const TensorShape &inferredShape, const ShapeInferenceMethod shapeInferenceMethod, const std::string &layerName, const unsigned int outputSlotIndex=0)
Definition: Layer.cpp:422
std::shared_ptr< ConstTensorHandle > m_InputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
const ConstTensorHandle * m_OutputGateBias
std::shared_ptr< ConstTensorHandle > m_CellToOutputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
void VerifyLayerConnections(unsigned int expectedConnections, const CheckLocation &location) const
Definition: Layer.cpp:378
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:324
std::shared_ptr< ConstTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
void ValidateTensorShapesFromInputs() override
Check if the input tensor shape(s) will lead to a valid configuration of LstmLayer.
Definition: LstmLayer.cpp:168
std::shared_ptr< ConstTensorHandle > m_CellBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
const ConstTensorHandle * m_CellLayerNormWeights
std::vector< std::reference_wrapper< std::shared_ptr< ConstTensorHandle > >> ConstantTensors
Definition: INetwork.hpp:114
LstmLayer * Clone(Graph &graph) const override
Creates a dynamically-allocated copy of this layer.
Definition: LstmLayer.cpp:80
An LstmDescriptor for the LstmLayer.
#define ARMNN_ASSERT_MSG(COND, MSG)
Definition: Assert.hpp:15
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:327
std::shared_ptr< ConstTensorHandle > m_RecurrentToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
bool m_PeepholeEnabled
Enable/disable peephole.
const ConstTensorHandle * m_CellToOutputWeights
std::shared_ptr< ConstTensorHandle > m_CellLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
#define ARMNN_ASSERT(COND)
Definition: Assert.hpp:14
LstmOptLayerNormParameters m_LayerNormParameters
Definition: LstmLayer.hpp:24
std::shared_ptr< ConstTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
const ConstTensorHandle * m_InputToCellWeights
virtual void ExecuteStrategy(const IConnectableLayer *layer, const armnn::BaseDescriptor &descriptor, const std::vector< armnn::ConstTensor > &constants, const char *name, const armnn::LayerBindingId id=0)=0
std::shared_ptr< ConstTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
const ConstTensorHandle * m_InputToForgetWeights
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
std::shared_ptr< ConstTensorHandle > m_ProjectionBias
A unique pointer to represent 1D weights tensor with dimensions [output_size].
const ConstTensorHandle * m_RecurrentToInputWeights
Layer::ConstantTensors GetConstantTensorsByRef() override
Retrieve the handles to the constant values stored by the layer.
Definition: LstmLayer.cpp:270
LstmOptPeepholeParameters m_PeepholeParameters
Definition: LstmLayer.hpp:23
void SetAdditionalInfo(QueueDescriptor &descriptor) const
Definition: Layer.cpp:274
const ConstTensorHandle * m_ForgetGateBias
LstmOptProjectionParameters m_ProjectionParameters
Definition: LstmLayer.hpp:22
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
std::shared_ptr< ConstTensorHandle > m_InputToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::shared_ptr< ConstTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
const ConstTensorHandle * m_CellToForgetWeights
const ConstTensorHandle * m_ProjectionBias
WorkloadInfo PrepInfoAndDesc(QueueDescriptor &descriptor) const
Helper function to reduce duplication in *LayerCreateWorkload.
LstmLayer(const LstmDescriptor &param, const char *name)
Constructor to create a LstmLayer.
Definition: LstmLayer.cpp:17
bool m_LayerNormEnabled
Enable/disable layer normalization.
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:326
const ConstTensorHandle * m_ForgetLayerNormWeights
virtual const TensorInfo & GetTensorInfo() const =0
LstmOptCifgParameters m_CifgParameters
Definition: LstmLayer.hpp:21
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:319
const ConstTensorHandle * m_InputLayerNormWeights
std::shared_ptr< ConstTensorHandle > m_ForgetLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
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.
Definition: LstmLayer.cpp:150
std::shared_ptr< ConstTensorHandle > m_CellToInputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
const void * Map(bool blocking=true)
RAII Managed resource Unmaps MemoryArea once out of scope.
const TensorInfo & GetTensorInfo(const ITensorHandle *tensorHandle)
float32 helpers
const ConstTensorHandle * m_CellToInputWeights
virtual std::unique_ptr< IWorkload > CreateWorkload(LayerType type, const QueueDescriptor &descriptor, const WorkloadInfo &info) const
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:92
const ConstTensorHandle * m_InputToInputWeights
ShapeInferenceMethod m_ShapeInferenceMethod
Definition: Layer.hpp:423
std::shared_ptr< ConstTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below...
Definition: Types.hpp:468
const ConstTensorHandle * m_RecurrentToOutputWeights