docs: def run_training(self):
      """Runs a Master."""
      self.train_path = os.path.join(self.output_path, 'train')
      self.model_path = os.path.join(self.output_path, 'model')
      self.is_master = self.task.type != 'worker'
      log_interval = 15
      self.eval_interval = 30
      if self.is_master and self.task.index > 0:
        raise Exception('Only one replica of master expected')
  
      if self.cluster:
        logging.info('Starting %s/%d', self.task.type, self.task.index)
        server = start_server(self.cluster, self.task)
        target = server.target
        device_fn = tf.train.replica_device_setter(
            ps_device='/job:ps',
            worker_device='/job:%s/task:%d' % (self.task.type, self.task.index),
            cluster=self.cluster)
        # We use a device_filter to limit the communication between this job
        # and the parameter servers, i.e., there is no need to directly
        # communicate with the other workers; attempting to do so can result
        # in reliability problems.
        device_filters = [
            '/job:ps', '/job:%s/task:%d' % (self.task.type, self.task.index)
        ]
        config = tf.ConfigProto(device_filters=device_filters)
      else:
        target = ''
        device_fn = ''
        config = None
  
      with tf.Graph().as_default() as graph:
        with tf.device(device_fn):
          # Build the training graph.
          self.tensors = self.model.build_train_graph(self.train_data_paths,
                                                      self.batch_size)
  
          # Add the variable initializer Op.
          init_op = tf.global_variables_initializer()
  
          # Create a saver for writing training checkpoints.
          self.saver = tf.train.Saver()
  
          # Build the summary operation based on the TF collection of Summaries.
          self.summary_op = tf.summary.merge_all()
  
      # Create a "supervisor", which oversees the training process.
      self.sv = tf.train.Supervisor(
          graph,
          is_chief=self.is_master,
          logdir=self.train_path,
          init_op=init_op,
          saver=self.saver,
          # Write summary_ops by hand.
          summary_op=None,
          global_step=self.tensors.global_step,
          # No saving; we do it manually in order to easily evaluate immediately
          # afterwards.
          save_model_secs=0)
  
      should_retry = True
      to_run = [self.tensors.global_step, self.tensors.train]
  
      while should_retry:
        try:
          should_retry = False
          with self.sv.managed_session(target, config=config) as session:
            self.start_time = start_time = time.time()
            self.last_save = self.last_log = 0
            self.global_step = self.last_global_step = 0
            self.local_step = self.last_local_step = 0
            self.last_global_time = self.last_local_time = start_time
  
            # Loop until the supervisor shuts down or max_steps have
            # completed.
            max_steps = self.max_steps
            while not self.sv.should_stop() and self.global_step < max_steps:
              try:
                # Run one step of the model.
                self.global_step = session.run(to_run)[0]
                self.local_step += 1
  
                self.now = time.time()
                is_time_to_eval = (self.now - self.last_save) > self.eval_interval
                is_time_to_log = (self.now - self.last_log) > log_interval
                should_eval = self.is_master and is_time_to_eval
                should_log = is_time_to_log or should_eval
  
                if should_log:
                  self.log(session)
  
                if should_eval:
                  self.eval(session)
              except tf.errors.AbortedError:
                should_retry = True
  
            if self.is_master:
              # Take the final checkpoint and compute the final accuracy.
              # self.saver.save(session, self.sv.save_path, self.tensors.global_step)
              self.eval(session)
  
        except tf.errors.AbortedError:
          print('Hitting an AbortedError. Trying it again.')
          should_retry = True
  
      # Export the model for inference.
      if self.is_master:
        self.model.export(tf.train.latest_checkpoint(self.train_path), self.model_path)
  
      # Ask for all the services to stop.
      self.sv.stop()