ArmNN
 25.02
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
UnidirectionalSequenceLstmLayer.cpp
Go to the documentation of this file.
1 //
2 // Copyright © 2021-2024 Arm Ltd and Contributors. All rights reserved.
3 // SPDX-License-Identifier: MIT
4 //
6 
7 #include "LayerCloneBase.hpp"
8 
9 #include <armnn/LstmParams.hpp>
10 #include <armnn/TypesUtils.hpp>
13 
14 namespace armnn
15 {
16 
19 {
20 }
21 
22 std::unique_ptr<IWorkload> UnidirectionalSequenceLstmLayer::CreateWorkload(const IWorkloadFactory& factory) const
23 {
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::UnidirectionalSequenceLstm, descriptor, PrepInfoAndDesc(descriptor));
78 }
79 
81 {
82  auto layer = CloneBase<UnidirectionalSequenceLstmLayer>(graph, m_Param, GetName());
83 
84  layer->m_BasicParameters.m_InputToForgetWeights = m_BasicParameters.m_InputToForgetWeights ?
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 
115  {
116  layer->m_ProjectionParameters.m_ProjectionWeights = m_ProjectionParameters.m_ProjectionWeights ?
118  layer->m_ProjectionParameters.m_ProjectionBias = m_ProjectionParameters.m_ProjectionBias ?
120  }
121 
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 
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 
151  const std::vector<TensorShape>& inputShapes) const
152 {
153  ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(inputShapes.size() == 3,
154  "inputShapes' size is \"" + std::to_string(inputShapes.size()) +
155  "\" - should be \"3\".");
156 
157  // Get input values for validation
158  unsigned int outputSize = inputShapes[1][1];
159 
160  std::vector<TensorShape> outShapes;
161  if (m_Param.m_TimeMajor)
162  {
163  outShapes.push_back(TensorShape({inputShapes[0][0], inputShapes[0][1], outputSize}));
164  }
165  else
166  {
167  outShapes.push_back(TensorShape({inputShapes[0][0], inputShapes[0][1], outputSize}));
168  }
169  return outShapes;
170 }
171 
173 {
175 
176  const TensorShape& outputShape = GetOutputSlot(2).GetTensorInfo().GetShape();
177 
179 
180  auto inferredShapes = InferOutputShapes( {
184  });
185 
186  if (inferredShapes.size() != 1)
187  {
188  throw armnn::LayerValidationException("inferredShapes has "
189  + std::to_string(inferredShapes.size()) +
190  " elements - should only have 1.");
191  }
192 
193  // Check if the weights are nullptr
195  {
196  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
197  "m_BasicParameters.m_InputToForgetWeights should not be null.");
198  }
199 
201  {
202  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
203  "m_BasicParameters.m_InputToCellWeights should not be null.");
204  }
205 
207  {
208  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
209  "m_BasicParameters.m_InputToOutputWeights should not be null.");
210  }
211 
213  {
214  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
215  "m_BasicParameters.m_RecurrentToForgetWeights should not be null.");
216  }
217 
219  {
220  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
221  "m_BasicParameters.m_RecurrentToCellWeights should not be null.");
222  }
223 
225  {
226  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
227  "m_BasicParameters.m_RecurrentToOutputWeights should not be null.");
228  }
229 
231  {
232  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
233  "m_BasicParameters.m_ForgetGateBias should not be null.");
234  }
235 
237  {
238  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
239  "m_BasicParameters.m_CellBias should not be null.");
240  }
241 
243  {
244  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
245  "m_BasicParameters.m_OutputGateBias should not be null.");
246  }
247 
248  if (!m_Param.m_CifgEnabled)
249  {
251  {
252  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
253  "m_CifgParameters.m_InputToInputWeights should not be null.");
254  }
255 
257  {
258  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
259  "m_CifgParameters.m_RecurrentToInputWeights should not be null.");
260  }
261 
263  {
264  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
265  "m_CifgParameters.m_InputGateBias should not be null.");
266  }
267  }
268  else
269  {
271  {
272  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
273  "m_CifgParameters.m_InputToInputWeights should not have a value "
274  "when CIFG is enabled.");
275  }
276 
278  {
279  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
280  "m_CifgParameters.m_RecurrentToInputWeights should not have a value "
281  "when CIFG is enabled.");
282  }
283 
285  {
286  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
287  "m_CifgParameters.m_InputGateBias should not have a value "
288  "when CIFG is enabled.");
289  }
290  }
291 
293  {
295  {
296  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
297  "m_ProjectionParameters.m_ProjectionWeights should not be null.");
298  }
299  }
300 
302  {
303  if (!m_Param.m_CifgEnabled)
304  {
306  {
307  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
308  "m_PeepholeParameters.m_CellToInputWeights should not be null "
309  "when Peephole is enabled and CIFG is disabled.");
310  }
311  }
312 
314  {
315  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
316  "m_PeepholeParameters.m_CellToForgetWeights should not be null.");
317  }
318 
320  {
321  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
322  "m_PeepholeParameters.m_CellToOutputWeights should not be null.");
323  }
324  }
325 
327  {
329  {
331  {
332  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
333  "m_LayerNormParameters.m_inputLayerNormWeights "
334  "should not be null.");
335  }
336  }
337 
339  {
340  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
341  "m_LayerNormParameters.m_forgetLayerNormWeights "
342  "should not be null.");
343  }
344 
346  {
347  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
348  "m_LayerNormParameters.m_cellLayerNormWeights "
349  "should not be null.");
350  }
351 
353  {
354  throw armnn::LayerValidationException("UnidirectionalSequenceLstmLayer: "
355  "m_LayerNormParameters.m_outputLayerNormWeights "
356  "should not be null.");
357  }
358  }
359 
360  ValidateAndCopyShape(outputShape, inferredShapes[0], m_ShapeInferenceMethod, "UnidirectionalSequenceLstmLayer");
361 }
362 
364 {
365  // For API stability DO NOT ALTER order and add new members to the end of vector
375 
376  // Cifg parameters
380 
381  // Projection parameters
384 
385  // Peephole parameters
389 
390  // Layer normalisation parameters
395 }
396 
398 {
399  std::vector<ConstTensor> constTensors;
400 
401  LstmDescriptor descriptor = GetParameters();
402 
412 
413  // Cifg parameters
417 
418  // Projection parameters
421 
422  // Peephole parameters
426 
427  // Layer normalisation parameters
432 
433  // First add mandatory/basic parameters
435  {
436  constTensors.emplace_back(ConstTensor(managedInputToForgetWeights.GetTensorInfo(),
437  managedInputToForgetWeights.Map()));
438  }
440  {
441  constTensors.emplace_back(ConstTensor(managedInputToCellWeights.GetTensorInfo(),
442  managedInputToCellWeights.Map()));
443  }
445  {
446  constTensors.emplace_back(ConstTensor(managedInputToOutputWeights.GetTensorInfo(),
447  managedInputToOutputWeights.Map()));
448  }
450  {
451  constTensors.emplace_back(ConstTensor(
452  managedRecurrentToForgetWeights.GetTensorInfo(),
453  managedRecurrentToForgetWeights.Map()));
454  }
456  {
457  constTensors.emplace_back(ConstTensor(
458  managedRecurrentToCellWeights.GetTensorInfo(),
459  managedRecurrentToCellWeights.Map()));
460  }
462  {
463  constTensors.emplace_back(ConstTensor(
464  managedRecurrentToOutputWeights.GetTensorInfo(),
465  managedRecurrentToOutputWeights.Map()));
466  }
467  if (m_BasicParameters.m_ForgetGateBias != nullptr)
468  {
469  constTensors.emplace_back(ConstTensor(managedForgetGateBias.GetTensorInfo(),
470  managedForgetGateBias.Map()));
471  }
472  if (m_BasicParameters.m_CellBias != nullptr)
473  {
474  constTensors.emplace_back(ConstTensor(managedCellBias.GetTensorInfo(),
475  managedCellBias.Map()));
476  }
477  if (m_BasicParameters.m_OutputGateBias != nullptr)
478  {
479  constTensors.emplace_back(ConstTensor(managedOutputGateBias.GetTensorInfo(),
480  managedOutputGateBias.Map()));
481  }
482 
483  // Add cifg parameters
484  if (!descriptor.m_CifgEnabled)
485  {
487  {
488  constTensors.emplace_back(ConstTensor(managedInputToInputWeights.GetTensorInfo(),
489  managedInputToInputWeights.Map()));
490  }
492  {
493  constTensors.emplace_back(ConstTensor(
494  managedRecurrentToInputWeights.GetTensorInfo(),
495  managedRecurrentToInputWeights.Map()));
496  }
497  if (m_CifgParameters.m_InputGateBias != nullptr)
498  {
499  constTensors.emplace_back(ConstTensor(managedInputGateBias.GetTensorInfo(),
500  managedInputGateBias.Map()));
501  }
502  }
503 
504  // Add peephole parameters
505  if (descriptor.m_PeepholeEnabled)
506  {
507  if (!descriptor.m_CifgEnabled)
508  {
510  {
511  constTensors.emplace_back(ConstTensor(managedCellToInputWeights.GetTensorInfo(),
512  managedCellToInputWeights.Map()));
513  }
514  }
516  {
517  constTensors.emplace_back(ConstTensor(managedCellToForgetWeights.GetTensorInfo(),
518  managedCellToForgetWeights.Map()));
519  }
521  {
522  constTensors.emplace_back(ConstTensor(managedCellToOutputWeights.GetTensorInfo(),
523  managedCellToOutputWeights.Map()));
524  }
525  }
526 
527  // Add projection parameters
528  if (descriptor.m_ProjectionEnabled)
529  {
531  {
532  constTensors.emplace_back(ConstTensor(managedProjectionWeights.GetTensorInfo(),
533  managedProjectionWeights.Map()));
534  }
536  {
537  constTensors.emplace_back(ConstTensor(managedProjectionBias.GetTensorInfo(),
538  managedProjectionBias.Map()));
539  }
540  }
541 
542  // Add norm parameters
543  if (descriptor.m_LayerNormEnabled)
544  {
545  if (!descriptor.m_CifgEnabled)
546  {
548  {
549  constTensors.emplace_back(ConstTensor(managedInputLayerNormWeights.GetTensorInfo(),
550  managedInputLayerNormWeights.Map()));
551  }
552  }
554  {
555  constTensors.emplace_back(ConstTensor(managedForgetLayerNormWeights.GetTensorInfo(),
556  managedForgetLayerNormWeights.Map()));
557  }
559  {
560  constTensors.emplace_back(ConstTensor(managedCellLayerNormWeights.GetTensorInfo(),
561  managedCellLayerNormWeights.Map()));
562  }
564  {
565  constTensors.emplace_back(ConstTensor(managedOutputLayerNormWeights.GetTensorInfo(),
566  managedOutputLayerNormWeights.Map()));
567  }
568  }
569 
570  strategy.ExecuteStrategy(this, GetParameters(), constTensors, GetName());
571 }
572 
573 } // namespace armnn
#define ARMNN_THROW_INVALIDARG_MSG_IF_FALSE(_cond, _str)
Definition: Exceptions.hpp:210
#define CHECK_LOCATION()
Definition: Exceptions.hpp:203
A tensor defined by a TensorInfo (shape and data type) and an immutable backing store.
Definition: Tensor.hpp:330
std::vector< std::reference_wrapper< const std::shared_ptr< ConstTensorHandle > >> ImmutableConstantTensors
Definition: INetwork.hpp:141
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
virtual std::unique_ptr< IWorkload > CreateWorkload(LayerType type, const QueueDescriptor &descriptor, const WorkloadInfo &info) const =0
Backends should implement their own CreateWorkload function with a switch statement.
const TensorInfo & GetTensorInfo() const override
Gets the TensorInfo for this InputSlot.
Definition: Layer.cpp:614
void VerifyLayerConnections(unsigned int expectedConnections, const CheckLocation &location) const
Definition: Layer.cpp:410
const OutputSlot & GetOutputSlot(unsigned int index=0) const override
Get the const output slot handle by slot index.
Definition: Layer.hpp:339
void VerifyShapeInferenceType(const TensorShape &outputShape, ShapeInferenceMethod shapeInferenceMethod)
Definition: Layer.cpp:526
const char * GetName() const override
Returns the name of the layer.
Definition: Layer.hpp:332
const InputSlot & GetInputSlot(unsigned int index) const override
Get a const input slot handle by slot index.
Definition: Layer.hpp:337
void ValidateAndCopyShape(const TensorShape &outputShape, const TensorShape &inferredShape, const ShapeInferenceMethod shapeInferenceMethod, const std::string &layerName, const unsigned int outputSlotIndex=0)
Definition: Layer.cpp:457
void SetAdditionalInfo(QueueDescriptor &descriptor) const
Definition: Layer.cpp:303
ShapeInferenceMethod m_ShapeInferenceMethod
Definition: Layer.hpp:441
WorkloadInfo PrepInfoAndDesc(QueueDescriptor &descriptor) const
Helper function to reduce duplication in *Layer::CreateWorkload.
LstmDescriptor m_Param
The parameters for the layer (not including tensor-valued weights etc.).
const LstmDescriptor & GetParameters() const override
const TensorInfo & GetTensorInfo() const
const void * Map(bool blocking=true)
RAII Managed resource Unmaps MemoryArea once out of scope.
const TensorInfo & GetTensorInfo() const override
Definition: Layer.cpp:100
const TensorShape & GetShape() const
Definition: Tensor.hpp:193
This layer represents a LSTM operation.
Layer::ImmutableConstantTensors GetConstantTensorsByRef() const override
Retrieve the handles to the constant values stored by the layer.
void ExecuteStrategy(IStrategy &strategy) const override
Apply a visitor to this layer.
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,...
UnidirectionalSequenceLstmLayer * Clone(Graph &graph) const override
Creates a dynamically-allocated copy of this layer.
void ValidateTensorShapesFromInputs() override
Check if the input tensor shape(s) will lead to a valid configuration of UnidirectionalSequenceLstmLa...
UnidirectionalSequenceLstmLayer(const LstmDescriptor &param, const char *name)
Constructor to create a UnidirectionalSequenceLstmLayer.
virtual std::unique_ptr< IWorkload > CreateWorkload(const IWorkloadFactory &factory) const override
Makes a workload for the UnidirectionalSequence LSTM type.
Copyright (c) 2021 ARM Limited and Contributors.
LayerType
When adding a new layer, adapt also the LastLayer enum value in the enum class LayerType below.
Definition: Types.hpp:494
std::shared_ptr< ConstTensorHandle > m_RecurrentToForgetWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
std::shared_ptr< ConstTensorHandle > m_CellBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_InputToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::shared_ptr< ConstTensorHandle > m_RecurrentToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
std::shared_ptr< ConstTensorHandle > m_OutputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
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_InputToCellWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::shared_ptr< ConstTensorHandle > m_RecurrentToOutputWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
std::shared_ptr< ConstTensorHandle > m_ForgetGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
An LstmDescriptor for the LstmLayer.
bool m_PeepholeEnabled
Enable/disable peephole.
bool m_TimeMajor
Enable/disable time major.
bool m_LayerNormEnabled
Enable/disable layer normalization.
bool m_ProjectionEnabled
Enable/disable the projection layer.
bool m_CifgEnabled
Enable/disable cifg (coupled input & forget gate).
std::shared_ptr< ConstTensorHandle > m_InputToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::shared_ptr< ConstTensorHandle > m_InputGateBias
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_RecurrentToInputWeights
A unique pointer to represent 2D weights tensor with dimensions [input_size, num_units].
std::shared_ptr< ConstTensorHandle > m_CellLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_InputLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_OutputLayerNormWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_ForgetLayerNormWeights
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].
std::shared_ptr< ConstTensorHandle > m_CellToInputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_CellToOutputWeights
A unique pointer to represent 1D weights tensor with dimensions [num_units].
std::shared_ptr< ConstTensorHandle > m_ProjectionBias
A unique pointer to represent 1D weights tensor with dimensions [output_size].
std::shared_ptr< ConstTensorHandle > m_ProjectionWeights
A unique pointer to represent 2D weights tensor with dimensions [output_size, num_units].
const ConstTensorHandle * m_RecurrentToOutputWeights
const ConstTensorHandle * m_RecurrentToForgetWeights