code: def on_train_init(
      self,
      base_config,
      experiment_name,
      output_directory,
      resume_directory,
      **kwargs,
  ):
      # Experiment may already have been set during hyperopt init, in
      # which case we don't want to create a new experiment / run, as
      # this should be handled by the executor.
      if self.experiment_id is None:
          mlflow.end_run()
          self.experiment_id = self.get_experiment_id(experiment_name)
          self.experiment_name = experiment_name
  
      active_run = mlflow.active_run()
      if active_run is not None:
          # Currently active run started by Ray Tune MLflow mixin or external run
          self.run = active_run
      else:
          run_id = None
          if resume_directory is not None:
              previous_runs = _get_runs(self.experiment_id)
              if len(previous_runs) > 0:
                  run_id = previous_runs[0].info.run_id
          if run_id is not None:
              self.run = mlflow.start_run(run_id=run_id)
          else:
              run_name = os.path.basename(output_directory)
              self.run = mlflow.start_run(
                  experiment_id=self.experiment_id, run_name=run_name
              )
  
      self.log_config(base_config)
  
imports: import logging
  import os
  import queue
  import threading
  from ludwig.api_annotations import DeveloperAPI, PublicAPI
  from ludwig.callbacks import Callback
  from ludwig.constants import TRAINER
  from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME, TRAIN_SET_METADATA_FILE_NAME
  from ludwig.types import TrainingSetMetadataDict
  from ludwig.utils.data_utils import chunk_dict, flatten_dict, save_json, to_json_dict
  from ludwig.utils.package_utils import LazyLoader
label_desc: Use image node_id 6 for calling the MlflowCallback obj's underlying member method code with example usage: obj.on_train_init(base_config, experiment_name, output_directory, resume_directory) without return types