class_docstr: ResNet bottleneck block with PosPool
  Arguments:
      down_conv_nn (len of 2) : sizes of input, output
      grid_size : size of the grid
      prev_grid_size : size of the grid at previous step.
              In case of a strided block, this is different than grid_size
      max_num_neighbors : maximum number of neighboors for the neighboor search
      position_embedding: Position Embedding type
      reduction: Reduction type in local aggregation
      output_conv: whether to use a convolution after aggregation
      activation : activation function
      has_bottleneck: wether to use the bottleneck or not
      bottleneck_ratio: bottleneck ratio, intermediate =  num_outputs // bottleneck ratio
      bn_momentum: the value used for the running_mean and running_var
      bn : batch norm (can be None -> no batch norm
class_docstr_tok: ["ResNet","bottleneck","block","with","PosPool","Arguments",":","down_conv_nn","(","len","of","2",")",":","sizes","of","input",",","output","grid_size",":","size","of","the","grid","prev_grid_size",":","size","of","the","grid","at","previous","step",".","In","case","of","a","strided","block",",","this","is","different","than","grid_size","max_num_neighbors",":","maximum","number","of","neighboors","for","the","neighboor","search","position_embedding",":","Position","Embedding","type","reduction",":","Reduction","type","in","local","aggregation","output_conv",":","whether","to","use","a","convolution","after","aggregation","activation",":","activation","function","has_bottleneck",":","wether","to","use","the","bottleneck","or","not","bottleneck_ratio",":","bottleneck","ratio",",","intermediate","=","num_outputs","\/\/","bottleneck","ratio","bn_momentum",":","the","value","used","for","the","running_mean","and","running_var","bn",":","batch","norm","(","can","be","None","-",">","no","batch","norm"]
code: def __init__(
      self,
      down_conv_nn=None,
      grid_size=None,
      prev_grid_size=None,
      sigma=1,
      max_num_neighbors=16,
      position_embedding="xyz",
      reduction="avg",
      output_conv=False,
      activation=torch.nn.LeakyReLU(negative_slope=0.2),
      has_bottleneck=True,
      bottleneck_ratio=2,
      bn_momentum=0.01,
      bn=FastBatchNorm1d,
      **kwargs,
  ):
      super(ResnetBBlock, self).__init__()
      assert len(down_conv_nn) == 2, "down_conv_nn should be of size 2"
      num_inputs, num_outputs = down_conv_nn
      d_2 = num_outputs // bottleneck_ratio
  
      self.is_strided = prev_grid_size != grid_size
      self.has_bottleneck = has_bottleneck
  
      # Main branch
      if self.has_bottleneck:
          channel_size = [d_2, d_2]
      else:
          channel_size = [num_inputs, num_outputs]
  
      self.aggregation = SimpleBlock(
          down_conv_nn=channel_size,
          grid_size=grid_size,
          prev_grid_size=prev_grid_size,
          sigma=sigma,
          max_num_neighbors=max_num_neighbors,
          position_embedding=position_embedding,
          reduction=reduction,
          output_conv=output_conv,
          activation=activation,
          bn_momentum=bn_momentum,
          bn=bn,
      )
  
      if self.has_bottleneck:
          if bn:
              self.unary_1 = torch.nn.Sequential(
                  Lin(num_inputs, d_2, bias=False),
                  bn(d_2, momentum=bn_momentum),
                  activation,
              )
              self.unary_2 = torch.nn.Sequential(
                  Lin(d_2, num_outputs, bias=False),
                  bn(num_outputs, momentum=bn_momentum),
              )
          else:
              self.unary_1 = torch.nn.Sequential(
                  Lin(num_inputs, d_2, bias=False), activation
              )
              self.unary_2 = torch.nn.Sequential(
                  Lin(d_2, num_outputs, bias=False)
              )
  
      # Shortcut
      if num_inputs != num_outputs:
          if bn:
              self.shortcut_op = torch.nn.Sequential(
                  Lin(num_inputs, num_outputs, bias=False),
                  bn(num_outputs, momentum=bn_momentum),
              )
          else:
              self.shortcut_op = Lin(
                  num_inputs, num_outputs, bias=False
              )
      else:
          self.shortcut_op = torch.nn.Identity()
  
      # Final activation
      self.activation = activation
  
imports: import torch
  import sys
  from torch.nn import Linear
  from .ops import PosPoolLayer
  from torch_points3d.core.common_modules.base_modules import BaseModule, FastBatchNorm1d
  from torch_points3d.core.spatial_ops import RadiusNeighbourFinder
  from torch_points3d.core.data_transform import GridSampling3D
  from torch_points3d.utils.enums import ConvolutionFormat
  from torch_points3d.utils.config import is_list
label_desc: Use image node_id 1 to create a new ResnetBBlock object from inherited base classes: BaseModule with example: obj = ResnetBBlock(down_conv_nn, grid_size, prev_grid_size, sigma, max_num_neighbors, position_embedding, reduction, output_conv, activation, has_bottleneck, bottleneck_ratio, bn_momentum, bn)