code: def training_step(self, batch, batch_idx, optimizer_idx=0):
      input = batch["input"]
      target = batch["target"]
      # TODO some authors report better training with random noise
      # target += torch.randn_like(target)/100
  
      if optimizer_idx == 0:
          output = self.forward(input)
          loss_dict = self.compute_losses(output, target)
          loss = loss_dict["loss"]
  
          self.log_dict(loss_dict)
  
          # logs only once per epoch not to slow down training
          if batch_idx == 0:
              batch.update({"output": output})
              self.log_images(batch)
  
      # train discriminator
      elif optimizer_idx == 1:
          # how well can it label as real?
          real_pred = self.discriminator(target)
          real = torch.ones_like(real_pred)
  
          output = self(input)
  
          real_loss = F.mse_loss(real_pred, real)
  
          # how well can it label as fake?
          fake_pred = self.discriminator(output)
          fake = torch.zeros_like(fake_pred)
          fake_loss = F.mse_loss(fake_pred, fake)
  
          loss = (real_loss + fake_loss) / 2
  
      return loss
  
file_path: BigDL/python/nano/client-application/VideoStylization/litmodels.py
imports: from typing import OrderedDict
  import torch
  import torch.nn
  import torch.nn.functional
  import pytorch_lightning
  from feature_model import FeaturesNet
  from original_models import Discriminator, Generator
label_desc: Use image node_id 3 for calling the LitModel obj's underlying member method code with example usage: obj.training_step(batch, batch_idx, optimizer_idx) and returns: loss