class_docstr: A block containing multiple subsequent LSTM layers followed by
  a final time-distributed dense layer with explicit non-linearity.
  
  The block expects the input tensors to have the from (batch-dim, time-dim, feature-dim).
  
  :param in_keys: One key identifying the input tensors.
  :param out_keys: One key identifying the output tensors.
  :param in_shapes: List of input shapes.
  :param hidden_size: The number of features in the hidden state.
  :param num_layers: Number of recurrent layers.
  :param bidirectional: If True, becomes a bidirectional LSTM.
  :param non_lin: The non-linearity to apply after the final layer.
class_docstr_tok: ["A","block","containing","multiple","subsequent","LSTM","layers","followed","by","a","final","time-distributed","dense","layer","with","explicit","non-linearity",".","The","block","expects","the","input","tensors","to","have","the","from","(","batch-dim",",","time-dim",",","feature-dim",")",".",":","param","in_keys",":","One","key","identifying","the","input","tensors",".",":","param","out_keys",":","One","key","identifying","the","output","tensors",".",":","param","in_shapes",":","List","of","input","shapes",".",":","param","hidden_size",":","The","number","of","features","in","the","hidden","state",".",":","param","num_layers",":","Number","of","recurrent","layers",".",":","param","bidirectional",":","If","True",",","becomes","a","bidirectional","LSTM",".",":","param","non_lin",":","The","non-linearity","to","apply","after","the","final","layer","."]
docstr: implementation of :class:`~maze.perception.blocks.shape_normalization.ShapeNormalizationBlock` interface
          
docstr_tok: ["implementation","of",":","class",":","`","~maze.perception.blocks.shape_normalization.ShapeNormalizationBlock","`","interface"]
code: def normalized_forward(
      self, block_input: Dict[str, torch.Tensor]
  ) -> Dict[str, torch.Tensor]:
      """implementation of :class:`~maze.perception.blocks.shape_normalization.ShapeNormalizationBlock` interface"""
  
      # check input tensor
      input_tensor = block_input[self.in_keys[0]]
      assert input_tensor.ndim == self.in_num_dims[0]
      assert input_tensor.shape[-2:] == self.in_shapes[0]
  
      # forward pass
      output_tensor, _ = self.net(input_tensor)
      output_tensor = self.final_dense(output_tensor)
  
      # check output tensor
      assert output_tensor.ndim == self.out_num_dims[0]
      assert output_tensor.shape[-1] == self.output_units
  
      return {self.out_keys[0]: output_tensor}
  
file_path: maze/maze/perception/blocks/recurrent/lstm.py
imports: from typing import Union, List, Dict, Sequence
  import torch
  from torch import nn
  from maze.core.annotations import override
  from maze.core.utils.factory import Factory
  from maze.perception.blocks.shape_normalization import ShapeNormalizationBlock
label_desc: Use image node_id 2 for calling the LSTMBlock obj's underlying member method code with example usage: obj.normalized_forward(block_input) and returns: dict