code: def train_step_single(self, Xi, yi, **fit_params):
          
          self.module_.train()
          self.optimizer_.zero_grad()
          y_pred = self.infer(Xi, **fit_params)
          loss = self.get_loss(y_pred, yi, X=Xi, training=True)
          loss.backward()
  
          self.notify(
              'on_grad_computed',
              named_parameters=TeeGenerator(self.module_.named_parameters()),
              X=Xi,
              y=yi
          )
  
          return {
              'loss': loss,
              'y_pred': y_pred,
              }
docs: Compute y_pred, loss value, and update net's gradients.
  
          The module is set to be in train mode (e.g. dropout is
          applied).
  
          Parameters
          ----------
          Xi : input data
            A batch of the input data.
  
          yi : target data
            A batch of the target data.
  
          **fit_params : dict
            Additional parameters passed to the ``forward`` method of
            the module and to the ``self.train_split`` call.