class_docstr: A block containing a LSTM perception block followed by a
  Slicing Block keeping only the output of the final time step.
  
  For details on flattening see :class:`~maze.perception.blocks.recurrent.lstm.LSTMBlock`.
  For details on dense layers see :class:`~maze.perception.blocks.general.slice.SliceBlock`.
  
  :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","a","LSTM","perception","block","followed","by","a","Slicing","Block","keeping","only","the","output","of","the","final","time","step",".","For","details","on","flattening","see",":","class",":","`","~maze.perception.blocks.recurrent.lstm.LSTMBlock","`",".","For","details","on","dense","layers","see",":","class",":","`","~maze.perception.blocks.general.slice.SliceBlock","`",".",":","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","."]
code: def __init__(
      self,
      in_keys: Union[str, List[str]],
      out_keys: Union[str, List[str]],
      in_shapes: Union[Sequence[int], List[Sequence[int]]],
      hidden_size: int,
      num_layers: int,
      bidirectional: bool,
      non_lin: Union[str, type(nn.Module)],
  ):
      super().__init__(
          in_keys=in_keys, out_keys=out_keys, in_shapes=in_shapes
      )
  
      out_keys_lstm = [f"{k}_lstm" for k in self.out_keys]
      self.lstm_block = LSTMBlock(
          in_keys=self.in_keys,
          out_keys=out_keys_lstm,
          in_shapes=self.in_shapes,
          hidden_size=hidden_size,
          num_layers=num_layers,
          bidirectional=bidirectional,
          non_lin=non_lin,
      )
  
      self.slice_block = SliceBlock(
          in_keys=out_keys_lstm,
          out_keys=out_keys,
          in_shapes=self.lstm_block.out_shapes(),
          slice_dim=-2,
          slice_idx=-1,
      )
  
file_path: maze/maze/perception/blocks/joint_blocks/lstm_last_step.py
imports: from typing import Union, List, Sequence, Dict
  import torch
  from torch import nn
  from maze.core.annotations import override
  from maze.perception.blocks.base import PerceptionBlock
  from maze.perception.blocks.general.slice import SliceBlock
  from maze.perception.blocks.recurrent.lstm import LSTMBlock
label_desc: Use image node_id 1 to create a new LSTMLastStepBlock object from inherited base classes: PerceptionBlock with example: obj = LSTMLastStepBlock(in_keys, out_keys, in_shapes, hidden_size, num_layers, bidirectional, non_lin)