class_docstr: apply the deformable kernel point convolution on a point cloud
  NB : it is the original version of KPConv, it is not the message passing version
  attributes:
  num_inputs : dimension of the input feature
  num_outputs : dimension of the output feature
  point_influence: influence distance of a single point (sigma * grid_size)
  n_kernel_points=15
  fixed="center"
  KP_influence="linear"
  aggregation_mode="sum"
  dimension=3
  modulated = False :   If deformable conv should be modulated
class_docstr_tok: ["apply","the","deformable","kernel","point","convolution","on","a","point","cloud","NB",":","it","is","the","original","version","of","KPConv",",","it","is","not","the","message","passing","version","attributes",":","num_inputs",":","dimension","of","the","input","feature","num_outputs",":","dimension","of","the","output","feature","point_influence",":","influence","distance","of","a","single","point","(","sigma","*","grid_size",")","n_kernel_points=15","fixed=","''","center","''","KP_influence=","''","linear","''","aggregation_mode=","''","sum","''","dimension=3","modulated","=","False",":","If","deformable","conv","should","be","modulated"]
code: def __init__(
      self,
      num_inputs,
      num_outputs,
      point_influence,
      n_kernel_points=15,
      fixed="center",
      KP_influence="linear",
      aggregation_mode="sum",
      dimension=3,
      modulated=False,
      loss_mode="fitting",
      add_one=False,
      **kwargs,
  ):
      super(KPConvDeformableLayer, self).__init__()
      self.kernel_radius = self._INFLUENCE_TO_RADIUS * point_influence
      self.point_influence = point_influence
      self.add_one = add_one
      self.num_inputs = num_inputs + self.add_one * 1
      self.num_outputs = num_outputs
  
      self.KP_influence = KP_influence
      self.n_kernel_points = n_kernel_points
      self.aggregation_mode = aggregation_mode
      self.modulated = modulated
      self.internal_losses = {
          self.PERMISSIVE_LOSS_KEY: 0.0,
          self.FITTING_LOSS_KEY: 0.0,
          self.REPULSION_LOSS_KEY: 0.0,
      }
      self.loss_mode = loss_mode
  
      # Initial kernel extent for this layer
      K_points_numpy = load_kernels(
          self.kernel_radius,
          n_kernel_points,
          num_kernels=1,
          dimension=dimension,
          fixed=fixed,
      )
      self.K_points = Parameter(
          torch.from_numpy(
              K_points_numpy.reshape((n_kernel_points, dimension))
          ).to(torch.float),
          requires_grad=False,
      )
  
      # Create independant weight for the first convolution and a bias term as no batch normalization happen
      if modulated:
          offset_dim = (dimension + 1) * self.n_kernel_points
      else:
          offset_dim = dimension * self.n_kernel_points
      offset_weights = torch.empty(
          [n_kernel_points, self.num_inputs, offset_dim],
          dtype=torch.float,
      )
      torch.nn.init.xavier_normal_(offset_weights)
      self.offset_weights = Parameter(offset_weights)
      self.offset_bias = Parameter(
          torch.zeros(offset_dim, dtype=torch.float)
      )
  
      # Main deformable weights
      weights = torch.empty(
          [n_kernel_points, self.num_inputs, num_outputs],
          dtype=torch.float,
      )
      torch.nn.init.xavier_normal_(weights)
      self.weight = Parameter(weights)
  
file_path: torch-points3d/torch_points3d/modules/KPConv/kernels.py
imports: import torch
  from torch.nn.parameter import Parameter
  from .kernel_utils import kernel_point_optimization_debug, load_kernels
  from .losses import fitting_loss, repulsion_loss, permissive_loss
  from .convolution_ops import *
  from torch_points3d.models.base_model import BaseInternalLossModule
label_desc: Use image node_id 1 to create a new KPConvDeformableLayer object from inherited base classes: BaseInternalLossModule with example: obj = KPConvDeformableLayer(num_inputs, num_outputs, point_influence, n_kernel_points, fixed, KP_influence, aggregation_mode, dimension, modulated, loss_mode, add_one)