code: def train(self, data_path, num_epoch):
      logging.info("num_epoch: %d", num_epoch)
      s_gen = DataGen(
          data_path,
          self.buckets,
          epochs=num_epoch,
          max_width=self.max_original_width,
      )
      step_time = 0.0
      loss = 0.0
      current_step = 0
      skipped_counter = 0
      writer = tf.compat.v1.summary.FileWriter(
          self.model_dir, self.sess.graph
      )
  
      logging.info("Starting the training process.")
      for batch in s_gen.gen(self.batch_size):
          current_step += 1
  
          start_time = time.time()
          # result = self.step(batch, self.forward_only)
          result = None
          try:
              result = self.step(batch, self.forward_only)
          except Exception as e:
              skipped_counter += 1
              logging.info(
                  "Step {} failed, batch skipped."
                  + " Total skipped: {}".format(
                      current_step, skipped_counter
                  )
              )
              logging.error(
                  "Step {} failed. Exception details: {}".format(
                      current_step, str(e)
                  )
              )
              continue
  
          loss += result["loss"] / self.steps_per_checkpoint
          curr_step_time = time.time() - start_time
          step_time += curr_step_time / self.steps_per_checkpoint
  
          # num_correct = 0
  
          # step_outputs = result['prediction']
          # grounds = batch['labels']
          # for output, ground in zip(step_outputs, grounds):
          #     if self.use_distance:
          #         incorrect = distance.levenshtein(output, ground)
          #         incorrect = float(incorrect) / len(ground)
          #         incorrect = min(1.0, incorrect)
          #     else:
          #         incorrect = 0 if output == ground else 1
          #     num_correct += 1. - incorrect
  
          writer.add_summary(result["summaries"], current_step)
  
          # precision = num_correct / len(batch['labels'])
          step_perplexity = (
              math.exp(result["loss"])
              if result["loss"] < 300
              else float("inf")
          )
  
          # logging.info('Step %i: %.3fs, precision: %.2f, loss: %f, perplexity: %f.'
          #              % (current_step, curr_step_time, precision*100,
          #                 result['loss'], step_perplexity))
  
          logging.info(
              "Step %i: %.3fs, loss: %f, perplexity: %f.",
              current_step,
              curr_step_time,
              result["loss"],
              step_perplexity,
          )
  
          # Once in a while, we save checkpoint, print statistics, and run evals.
          if current_step % self.steps_per_checkpoint == 0:
              perplexity = (
                  math.exp(loss) if loss < 300 else float("inf")
              )
              # Print statistics for the previous epoch.
              logging.info(
                  "Global step %d. Time: %.3f, loss: %f, perplexity: %.2f.",
                  self.sess.run(self.global_step),
                  step_time,
                  loss,
                  perplexity,
              )
              # Save checkpoint and reset timer and loss.
              logging.info("Saving the model at step %d.", current_step)
              self.saver_all.save(
                  self.sess,
                  self.checkpoint_path,
                  global_step=self.global_step,
              )
              step_time, loss = 0.0, 0.0
  
      # Print statistics for the previous epoch.
      perplexity = math.exp(loss) if loss < 300 else float("inf")
      logging.info(
          "Global step %d. Time: %.3f, loss: %f, perplexity: %.2f.",
          self.sess.run(self.global_step),
          step_time,
          loss,
          perplexity,
      )
  
      if skipped_counter:
          logging.info(
              "Skipped {} batches due to errors.".format(
                  skipped_counter
              )
          )
  
      # Save checkpoint and reset timer and loss.
      logging.info(
          "Finishing the training and saving the model at step %d.",
          current_step,
      )
      self.saver_all.save(
          self.sess, self.checkpoint_path, global_step=self.global_step
      )
  
imports: from __future__ import absolute_import
  from __future__ import division
  import time
  import os
  import math
  import logging
  import sys
  import distance
  import numpy
  import tensorflow
  from six.moves import xrange
  from .cnn import CNN
  from .seq2seq_model import Seq2SeqModel
  from ..util.data_gen import DataGen
  from ..util.visualizations import visualize_attention
label_desc: Use image node_id 4 for calling the Model obj's underlying member method code with example usage: obj.train(data_path, num_epoch) without return types