class_docstr: PointNet2 with multi-scale grouping
  descriptors network for registration that uses feature propogation layers
  
  Parameters
  ----------
  num_classes: int
      Number of semantics classes to predict over -- size of softmax classifier that run for each point
  input_channels: int = 6
      Number of input channels in the feature descriptor for each point.  If the point cloud is Nx9, this
      value should be 6 as in an Nx9 point cloud, 3 of the channels are xyz, and 6 are feature descriptors
  use_xyz: bool = True
      Whether or not to use the xyz position of a point as a feature
docstr: Unpack input data from the dataloader and perform necessary pre-processing steps.
  Parameters:
      input: a dictionary that contains the data itself and its metadata information.
  Sets:
      self.input:
          x -- Features [B, C, N]
          pos -- Points [B, N, 3]
docstr_tok: ["Unpack","input","data","from","the","dataloader","and","perform","necessary","pre-processing","steps",".","Parameters",":","input",":","a","dictionary","that","contains","the","data","itself","and","its","metadata","information",".","Sets",":","self.input",":","x","--","Features","[","B",",","C",",","N","]","pos","--","Points","[","B",",","N",",","3","]"]
code: def set_input(self, data, device):
      """Unpack input data from the dataloader and perform necessary pre-processing steps.
      Parameters:
          input: a dictionary that contains the data itself and its metadata information.
      Sets:
          self.input:
              x -- Features [B, C, N]
              pos -- Points [B, N, 3]
      """
      assert len(data.pos.shape) == 3
  
      if data.x is not None:
          x = data.x.transpose(1, 2).contiguous()
      else:
          x = None
      self.input = Data(x=x, pos=data.pos).to(device)
  
      if hasattr(data, "pos_target"):
          if data.x_target is not None:
              x = data.x_target.transpose(1, 2).contiguous()
          else:
              x = None
          self.input_target = Data(x=x, pos=data.pos_target).to(device)
          self.match = data.pair_ind.to(torch.long).to(device)
          self.size_match = data.size_pair_ind.to(torch.long).to(device)
      else:
          self.match = None
  
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 2 for calling the FragmentPointNet2_D obj's underlying member method code with example usage: obj.set_input(data, device) without return types