class_docstr: PointNet2 with multi-scale grouping
  metric learning siamese network that uses feature propogation layers
docstr: forward pass of the network
docstr_tok: ["forward","pass","of","the","network"]
code: def forward(self, *args, **kwargs):
      r"""
      forward pass of the network
      """
      data = self.input
      labels = data.y
      for i in range(len(self.down_modules)):
          data = self.down_modules[i](data)
  
      # size after pointnet B x D x N
      last_feature = torch.mean(data.x, dim=-1)
      # size after global pooling B x D
      self.output = self.FC_layer(last_feature)
      self.output = F.normalize(self.output, p=2, dim=1)
      if labels is None:
          return self.output
      hard_pairs = None
      if self.miner_module is not None:
          hard_pairs = self.miner_module(self.output, labels)
      self.loss_reg = self.metric_loss_module(
          self.output, labels, hard_pairs
      )
      self.internal = self.get_internal_loss()
      self.loss = self.loss_reg + self.internal
      return self.output
  
imports: import torch
  import torch.nn.functional
  from torch.nn import Linear
  from torch.nn import Sequential
  from torch_geometric.data import Data
  import logging
  from torch_points3d.core.losses import *
  from torch_points3d.modules.pointnet2 import *
  from torch_points3d.core.common_modules import MLP
  from torch_points3d.models.base_architectures import BackboneBasedModel
  from torch_points3d.models.base_architectures import UnetBasedModel
  from torch_points3d.core.common_modules.dense_modules import Conv1D
  from torch_points3d.core.common_modules.base_modules import Seq
  from torch_points3d.models.registration.base import FragmentBaseModel
label_desc: Use image node_id 4 for calling the PatchPointNet2_D obj's underlying member method code with example usage: obj.forward() and returns: self, self