class_docstr: Perception block normalizing the input and de-normalizing the output tensor dimensions.
  
  Examples where this interface needs to be implemented are Dense Layers (batch-dim, feature-dim)
  or Convolution Blocks (batch-dim, feature-dim, row-dim, column-dim)
  
  :param in_keys: Keys identifying the input tensors.
  :param out_keys: Keys identifying the output tensors.
  :param in_shapes: List of input shapes.
  :param in_num_dims: Required number of dimensions for corresponding input.
  :param out_num_dims: Required number of dimensions for corresponding output.
class_docstr_tok: ["Perception","block","normalizing","the","input","and","de-normalizing","the","output","tensor","dimensions",".","Examples","where","this","interface","needs","to","be","implemented","are","Dense","Layers","(","batch-dim",",","feature-dim",")","or","Convolution","Blocks","(","batch-dim",",","feature-dim",",","row-dim",",","column-dim",")",":","param","in_keys",":","Keys","identifying","the","input","tensors",".",":","param","out_keys",":","Keys","identifying","the","output","tensors",".",":","param","in_shapes",":","List","of","input","shapes",".",":","param","in_num_dims",":","Required","number","of","dimensions","for","corresponding","input",".",":","param","out_num_dims",":","Required","number","of","dimensions","for","corresponding","output","."]
docstr: De-normalizes the tensor dictionary to the original batch dimensions.
          
docstr_tok: ["De-normalizes","the","tensor","dictionary","to","the","original","batch","dimensions","."]
code: def _de_normalize(
      self,
      tensor_dict: Dict[str, torch.Tensor],
      original_in_batch_shape: Sequence[int],
  ):
      """De-normalizes the tensor dictionary to the original batch dimensions."""
  
      # extract common batch dimension of input tensors
      original_batch_shape = list(original_in_batch_shape)
      num_batch_dims = len(original_batch_shape)
  
      # reshape output tensors to original batch dimensions
      for i, out_key in enumerate(self.out_keys):
          out_tensor = tensor_dict[out_key]
          num_feat_dims = self.out_num_dims[i] - 1
          feature_shape = list(out_tensor.shape[-num_feat_dims:])
          new_shape = original_batch_shape + feature_shape
          tensor_dict[out_key] = out_tensor.reshape(new_shape)
  
          # shape assertions
          assert (
              num_batch_dims + num_feat_dims
              == tensor_dict[out_key].ndim
          )
  
      return tensor_dict
  
file_path: maze/maze/perception/blocks/shape_normalization.py
imports: from abc import ABC, abstractmethod
  from typing import Dict, Union, List, Tuple, Sequence
  import numpy
  import torch
  from maze.core.annotations import override
  from maze.perception.blocks.base import PerceptionBlock
label_desc: Use image node_id 5 for calling the ShapeNormalizationBlock obj's underlying member method code with example usage: obj._de_normalize(tensor_dict, original_in_batch_shape) and returns: tensor_dict