code: def training_step(self, batch, batch_idx):
      # data preparation
      data_feature, data_attribute = batch
      optimizer_d, optimizer_attr_d, optimizer_g = self.optimizers()
  
      # generate noise input
      real_attribute_input_noise = gen_attribute_input_noise(
          data_feature.shape[0]
      )
      addi_attribute_input_noise = gen_attribute_input_noise(
          data_feature.shape[0]
      )
      feature_input_noise = gen_feature_input_noise(
          data_feature.shape[0], self.length
      )
      real_attribute_input_noise = torch.from_numpy(
          real_attribute_input_noise
      ).float()
      addi_attribute_input_noise = torch.from_numpy(
          addi_attribute_input_noise
      ).float()
      feature_input_noise = torch.from_numpy(
          feature_input_noise
      ).float()
  
      # g backward
      # open the generator grad since we need to update the weights in g
      for p in self.model.generator.parameters():
          p.requires_grad = True
      for i in range(self.g_rounds):
          d_fake, attr_d_fake, d_real, attr_d_real = self(
              data_feature,
              real_attribute_input_noise,
              addi_attribute_input_noise,
              feature_input_noise,
              data_attribute,
          )
          g_loss, _, _ = doppelganger_loss(
              d_fake, attr_d_fake, d_real, attr_d_real
          )
          optimizer_g.zero_grad()
          self.manual_backward(g_loss)
          optimizer_g.step()
  
      # d backward
      # close the generator grad since we only need to update the weights in d
      for p in self.model.generator.parameters():
          p.requires_grad = False
      for i in range(self.d_rounds):
          d_fake, attr_d_fake, d_real, attr_d_real = self(
              data_feature,
              real_attribute_input_noise,
              addi_attribute_input_noise,
              feature_input_noise,
              data_attribute,
          )
          _, d_loss, attr_d_loss = doppelganger_loss(
              d_fake,
              attr_d_fake,
              d_real,
              attr_d_real,
              g_attr_d_coe=self.hparams.g_attr_d_coe,
              gradient_penalty=True,
              discriminator=self.model.discriminator,
              attr_discriminator=self.model.attr_discriminator,
              g_output_feature_train_tf=self.model.g_feature_train,
              g_output_attribute_train_tf=self.model.g_attribute_train,
              real_feature_pl=self.model.real_feature_pl,
              real_attribute_pl=self.model.real_attribute_pl,
              d_gp_coe=self.hparams.d_gp_coe,
              attr_d_gp_coe=self.hparams.attr_d_gp_coe,
          )
          optimizer_d.zero_grad()
          optimizer_attr_d.zero_grad()
          self.manual_backward(d_loss)
          self.manual_backward(attr_d_loss)
          optimizer_d.step()
          optimizer_attr_d.step()
  
          # log tqdm
          self.log(
              "g_loss",
              g_loss.item(),
              on_step=True,
              on_epoch=True,
              prog_bar=True,
              logger=True,
          )
          self.log(
              "d_loss",
              d_loss.item(),
              on_step=True,
              on_epoch=True,
              prog_bar=True,
              logger=True,
          )
          self.log(
              "attr_d_loss",
              attr_d_loss.item(),
              on_step=True,
              on_epoch=True,
              prog_bar=True,
              logger=True,
          )
  
imports: import os
  import numpy
  import sys
  from collections import OrderedDict
  import math
  import torch
  import torch.nn.functional
  from torch import nn
  from pytorch_lightning import LightningModule
  from pytorch_lightning import seed_everything
  from .doppelganger import DoppelGANger
  from .network import RNNInitialStateType
  from .loss import doppelganger_loss
  from .util import gen_attribute_input_noise, gen_feature_input_noise, gen_feature_input_data_free, renormalize_per_sample
label_desc: Use image node_id 3 for calling the DoppelGANger_pl obj's underlying member method code with example usage: obj.training_step(batch, batch_idx) without return types