code: def forward(self, x, cat_vec=None):
      batch_size = x.shape[0]
      h = x.permute(0, 2, 1)
      num_points = h.shape[2]
      if self.use_transform:
          trans = self.transform1(h)
          h = h.transpose(2, 1)
          h = torch.bmm(h, trans)
          h = h.transpose(2, 1)
          h = F.relu(self.trans_bn1(h))
  
      mid_feat = []
      for conv, bn in zip(self.conv1, self.bn1):
          h = conv(h)
          h = bn(h)
          h = F.relu(h)
          mid_feat.append(h)
  
      if self.use_transform:
          trans = self.transform2(h)
          h = h.transpose(2, 1)
          h = torch.bmm(h, trans)
          h = h.transpose(2, 1)
          h = F.relu(self.trans_bn2(h))
          mid_feat.append(h)
  
      for conv, bn in zip(self.conv2, self.bn2):
          h = conv(h)
          h = bn(h)
          h = F.relu(h)
          mid_feat.append(h)
  
      h = self.conv_max(h)
      h = self.bn_max(h)
      h = (
          self.maxpool(h)
          .view(batch_size, -1, 1)
          .repeat(1, 1, num_points)
      )
      mid_feat.append(h)
      if cat_vec is not None:
          mid_feat.append(cat_vec)
      h = torch.cat(mid_feat, 1)
      for conv, bn in zip(self.conv3, self.bn3):
          h = conv(h)
          h = bn(h)
          h = F.relu(h)
  
      out = self.conv_out(h)
      return out
  
file_path: dgl/examples/pytorch/pointcloud/pointnet/pointnet_partseg.py
imports: import numpy
  import torch
  import torch.nn
  import torch.nn.functional
  from torch.autograd import Variable
label_desc: Use image node_id 2 for calling the PointNetPartSeg obj's underlying member method code with example usage: obj.forward(x, cat_vec) and returns: out