class_docstr: Feature Transform Net as proposed in https://arxiv.org/abs/1612.00593. This Module implements three
  convolutional stacks, each consisting of a 1d Convolution (kernel size =1) followed by an optional batch
  normalization and a specified non-linearity. The resulting output of the convolutions is then pooled in the
  point dimension (N) with the specified pooling method. Next two fully connected layers (again with optional
  batch norm and non linearity) are process the now two dimensional data. Finally one fully connected layer is
  applied before reshaping the data into the output format: BxKxK, where B is the batch dimension, N is the number
  of points and K is the number of features. The input to the module should have the shape BxKxN.
  
  :param num_features: Number of input features (K).
  :param num_points: Number of input points (N).
  :param embedding_dim: The embedding dimension to use (Paper: 1024).
  :param pooling_func_name: A string in ('max', 'mean', 'sum') specifying the pooling function to use. (Paper:
  'max')
  :param use_batch_norm: Specify whether to use batch_norm (like in original paper).
  :param non_lin: The non-linearity to apply after each fully connected layer.
  :param use_masking: Specify whether to use masking.
  
   
class_docstr_tok: ["Feature","Transform","Net","as","proposed","in","https",":","\/\/arxiv.org\/abs\/1612.00593",".","This","Module","implements","three","convolutional","stacks",",","each","consisting","of","a","1d","Convolution","(","kernel","size","=1",")","followed","by","an","optional","batch","normalization","and","a","specified","non-linearity",".","The","resulting","output","of","the","convolutions","is","then","pooled","in","the","point","dimension","(","N",")","with","the","specified","pooling","method",".","Next","two","fully","connected","layers","(","again","with","optional","batch","norm","and","non","linearity",")","are","process","the","now","two","dimensional","data",".","Finally","one","fully","connected","layer","is","applied","before","reshaping","the","data","into","the","output","format",":","BxKxK",",","where","B","is","the","batch","dimension",",","N","is","the","number","of","points","and","K","is","the","number","of","features",".","The","input","to","the","module","should","have","the","shape","BxKxN",".",":","param","num_features",":","Number","of","input","features","(","K",")",".",":","param","num_points",":","Number","of","input","points","(","N",")",".",":","param","embedding_dim",":","The","embedding","dimension","to","use","(","Paper",":","1024",")",".",":","param","pooling_func_name",":","A","string","in","(","'max","'",",","'mean","'",",","'sum","'",")","specifying","the","pooling","function","to","use",".","(","Paper",":","'max","'",")",":","param","use_batch_norm",":","Specify","whether","to","use","batch_norm","(","like","in","original","paper",")",".",":","param","non_lin",":","The","non-linearity","to","apply","after","each","fully","connected","layer",".",":","param","use_masking",":","Specify","whether","to","use","masking","."]
docstr: Forward pass through the transformer module
  
  :param input_tensor: Input to the network (BB, KK, NN)
  :param masking_tensor: Optional masking tensor for the pooling operation (BB, NN).
  :return: A transformation matrix of the form (BB, KK, KK)
docstr_tok: ["Forward","pass","through","the","transformer","module",":","param","input_tensor",":","Input","to","the","network","(","BB",",","KK",",","NN",")",":","param","masking_tensor",":","Optional","masking","tensor","for","the","pooling","operation","(","BB",",","NN",")",".",":","return",":","A","transformation","matrix","of","the","form","(","BB",",","KK",",","KK",")"]
code: def forward(
      self, input_tensor, masking_tensor: Optional[torch.Tensor]
  ):
      """Forward pass through the transformer module
  
      :param input_tensor: Input to the network (BB, KK, NN)
      :param masking_tensor: Optional masking tensor for the pooling operation (BB, NN).
      :return: A transformation matrix of the form (BB, KK, KK)
      """
  
      batch_size = input_tensor.shape[0]
  
      # input_tensor: (BB, KK, NN)
      out = self.conv1(input_tensor)
      if self._use_batch_norm and batch_size > 1:
          out = self.bn1(out)
      out = self.non_lin_1(out)
  
      # out: (BB, embedding_dim // 16, NN)
      out = self.conv2(out)
      if self._use_batch_norm and batch_size > 1:
          out = self.bn2(out)
      out = self.non_lin_2(out)
  
      # out: (BB, embedding_dim // 8, NN)
      out = self.conv3(out)
      if self._use_batch_norm and batch_size > 1:
          out = self.bn3(out)
      out = self.non_lin_3(out)
      # out: (BB, embedding_dim , NN)
  
      # Pooling
      # out: (BB, embedding_dim, NN)
      masking_input = {"in_tensor": out.transpose(2, 1)}
      if self.use_masking:
          masking_input["mask_tensor"] = masking_tensor
      out = self.pooling_block(masking_input)["masking_out"]
      # output_tensor: (BB, embedding_dim)
  
      # out: (BB, embedding_dim)
      out = self.fc1(out)
      if self._use_batch_norm and batch_size > 1:
          out = self.bn4(out)
      out = self.non_lin_4(out)
  
      # out: (BB, embedding_dim//2)
      out = self.fc2(out)
      if self._use_batch_norm and batch_size > 1:
          out = self.bn5(out)
      out = self.non_lin_5(out)
  
      # out: (BB, embedding_dim//4)
      out = self.fc3(out)
      # out: (BB, num_features ** 2)
  
      identity = (
          torch.flatten(torch.eye(self._num_features), start_dim=-2)
          .to(torch.float32)
          .to(out.device)
      )
      identity = identity.repeat(batch_size, 1)
      out = out + identity
  
      # out: (BB, num_features ** 2)
      out = out.view(-1, self._num_features, self._num_features)
      # out: (BB, num_features, num_features)
      return out
  
file_path: maze/maze/perception/blocks/feed_forward/point_net.py
imports: from collections import OrderedDict
  from typing import Union, List, Dict, Sequence, Optional
  import torch
  from torch import nn
  from maze.core.annotations import override
  from maze.core.utils.factory import Factory
  from maze.perception.blocks.general.masked_global_pooling import MaskedGlobalPoolingBlock
  from maze.perception.blocks.shape_normalization import ShapeNormalizationBlock
label_desc: Use image node_id 2 for calling the PointNetFeatureTransformNet obj's underlying member method code with example usage: obj.forward(input_tensor, masking_tensor) and returns: out