code: def forward(self, x, prior=None):
      x = self.initial_bn(x)
  
      bs = x.shape[0]  # batch size
      if prior is None:
          prior = torch.ones((bs, self.attention_dim)).to(x.device)
  
      M_loss = 0
      att = self.initial_splitter(x)[:, self.n_d :]
      steps_output = []
      for step in range(self.n_steps):
          M = self.att_transformers[step](prior, att)
          M_loss += torch.mean(
              torch.sum(
                  torch.mul(M, torch.log(M + self.epsilon)), dim=1
              )
          )
          # update prior
          prior = torch.mul(self.gamma - M, prior)
          # output
          M_feature_level = torch.matmul(M, self.group_attention_matrix)
          masked_x = torch.mul(M_feature_level, x)
          out = self.feat_transformers[step](masked_x)
          d = ReLU()(out[:, : self.n_d])
          steps_output.append(d)
          # update attention
          att = out[:, self.n_d :]
  
      M_loss /= self.n_steps
      return steps_output, M_loss
  
imports: import torch
  from torch.nn import Linear, BatchNorm1d, ReLU
  import numpy
  from pytorch_tabnet import sparsemax
label_desc: Use image node_id 2 for calling the TabNetEncoder obj's underlying member method code with example usage: obj.forward(x, prior) and returns: steps_output,  M_loss