code: def cli(sys_argv):
      parser = argparse.ArgumentParser(
          description="This script trains and evaluates a model",
          prog="ludwig experiment",
          usage="%(prog)s [options]",
      )
  
      # ----------------------------
      # Experiment naming parameters
      # ----------------------------
      parser.add_argument(
          "--output_directory",
          type=str,
          default="results",
          help="directory that contains the results",
      )
      parser.add_argument(
          "--experiment_name",
          type=str,
          default="experiment",
          help="experiment name",
      )
      parser.add_argument(
          "--model_name",
          type=str,
          default="run",
          help="name for the model",
      )
  
      # ---------------
      # Data parameters
      # ---------------
      parser.add_argument(
          "--dataset",
          help="input data file path. "
          "If it has a split column, it will be used for splitting "
          "(0: train, 1: validation, 2: test), "
          "otherwise the dataset will be randomly split",
      )
      parser.add_argument(
          "--training_set", help="input train data file path"
      )
      parser.add_argument(
          "--validation_set", help="input validation data file path"
      )
      parser.add_argument(
          "--test_set", help="input test data file path"
      )
  
      parser.add_argument(
          "--training_set_metadata",
          help="input metadata JSON file path. An intermediate preprocessed file "
          "containing the mappings of the input file created "
          "the first time a file is used, in the same directory "
          "with the same name and a .json extension",
      )
  
      parser.add_argument(
          "--data_format",
          help="format of the input data",
          default="auto",
          choices=[
              "auto",
              "csv",
              "excel",
              "feather",
              "fwf",
              "hdf5",
              "html" "tables",
              "json",
              "jsonl",
              "parquet",
              "pickle",
              "sas",
              "spss",
              "stata",
              "tsv",
          ],
      )
  
      parser.add_argument(
          "-es",
          "--eval_split",
          default=TEST,
          choices=[TRAINING, VALIDATION, TEST, FULL],
          help="the split to evaluate the model on",
      )
  
      parser.add_argument(
          "-sspi",
          "--skip_save_processed_input",
          help="skips saving intermediate HDF5 and JSON files",
          action="store_true",
          default=False,
      )
      parser.add_argument(
          "-ssuo",
          "--skip_save_unprocessed_output",
          help="skips saving intermediate NPY output files",
          action="store_true",
          default=False,
      )
  
      # -----------------
      # K-fold parameters
      # -----------------
      parser.add_argument(
          "-kf",
          "--k_fold",
          type=int,
          default=None,
          help="number of folds for a k-fold cross validation run ",
      )
      parser.add_argument(
          "-skfsi",
          "--skip_save_k_fold_split_indices",
          action="store_true",
          default=False,
          help="disables saving indices generated to split training data set "
          "for the k-fold cross validation run, but if it is not needed "
          "turning it off can slightly increase the overall speed",
      )
  
      # ----------------
      # Model parameters
      # ----------------
      config = parser.add_mutually_exclusive_group(required=True)
      config.add_argument(
          "-c",
          "--config",
          type=load_yaml,
          help="Path to the YAML file containing the model configuration",
      )
      config.add_argument(
          "-cs",
          "--config_str",
          dest="config",
          type=load_config_from_str,
          help="JSON or YAML serialized string of the model configuration",
      )
  
      parser.add_argument(
          "-mlp",
          "--model_load_path",
          help="path of a pretrained model to load as initialization",
      )
      parser.add_argument(
          "-mrp",
          "--model_resume_path",
          help="path of the model directory to resume training of",
      )
      parser.add_argument(
          "-sstd",
          "--skip_save_training_description",
          action="store_true",
          default=False,
          help="disables saving the description JSON file",
      )
      parser.add_argument(
          "-ssts",
          "--skip_save_training_statistics",
          action="store_true",
          default=False,
          help="disables saving training statistics JSON file",
      )
      parser.add_argument(
          "-sstp",
          "--skip_save_predictions",
          help="skips saving test predictions CSV files",
          action="store_true",
          default=False,
      )
      parser.add_argument(
          "-sstes",
          "--skip_save_eval_stats",
          help="skips saving eval statistics JSON file",
          action="store_true",
          default=False,
      )
      parser.add_argument(
          "-ssm",
          "--skip_save_model",
          action="store_true",
          default=False,
          help="disables saving model weights and hyperparameters each time "
          "the model improves. "
          "By default Ludwig saves model weights after each epoch "
          "the validation metric improves, but if the model is really big "
          "that can be time consuming. If you do not want to keep "
          "the weights and just find out what performance a model can get "
          "with a set of hyperparameters, use this parameter to skip it,"
          "but the model will not be loadable later on",
      )
      parser.add_argument(
          "-ssp",
          "--skip_save_progress",
          action="store_true",
          default=False,
          help="disables saving progress each epoch. By default Ludwig saves "
          "weights and stats after each epoch for enabling resuming "
          "of training, but if the model is really big that can be "
          "time consuming and will uses twice as much space, use "
          "this parameter to skip it, but training cannot be resumed "
          "later on",
      )
      parser.add_argument(
          "-ssl",
          "--skip_save_log",
          action="store_true",
          default=False,
          help="disables saving TensorBoard logs. By default Ludwig saves "
          "logs for the TensorBoard, but if it is not needed turning it off "
          "can slightly increase the overall speed",
      )
  
      # ------------------
      # Runtime parameters
      # ------------------
      parser.add_argument(
          "-rs",
          "--random_seed",
          type=int,
          default=42,
          help="a random seed that is going to be used anywhere there is a call "
          "to a random number generator: data splitting, parameter "
          "initialization and training set shuffling",
      )
      parser.add_argument(
          "-g",
          "--gpus",
          nargs="+",
          type=int,
          default=None,
          help="list of GPUs to use",
      )
      parser.add_argument(
          "-gml",
          "--gpu_memory_limit",
          type=float,
          default=None,
          help="maximum memory fraction [0, 1] allowed to allocate per GPU device",
      )
      parser.add_argument(
          "-dpt",
          "--disable_parallel_threads",
          action="store_false",
          dest="allow_parallel_threads",
          help="disable PyTorch from using multithreading for reproducibility",
      )
      parser.add_argument(
          "-b",
          "--backend",
          help="specifies backend to use for parallel / distributed execution, "
          "defaults to local execution or Horovod if called using horovodrun",
          choices=ALL_BACKENDS,
      )
      parser.add_argument(
          "-l",
          "--logging_level",
          default="info",
          help="the level of logging to use",
          choices=[
              "critical",
              "error",
              "warning",
              "info",
              "debug",
              "notset",
          ],
      )
  
      add_contrib_callback_args(parser)
      args = parser.parse_args(sys_argv)
  
      args.callbacks = args.callbacks or []
      for callback in args.callbacks:
          callback.on_cmdline("experiment", *sys_argv)
  
      args.logging_level = get_logging_level_registry()[
          args.logging_level
      ]
      logging.getLogger("ludwig").setLevel(args.logging_level)
      global logger
      logger = logging.getLogger("ludwig.experiment")
  
      args.backend = initialize_backend(
          args.backend or args.config.get("backend")
      )
      if args.backend.is_coordinator():
          print_ludwig("Experiment", LUDWIG_VERSION)
  
      if args.k_fold is None:
          experiment_cli(**vars(args))
      else:
          kfold_cross_validate_cli(**vars(args))
  
file_path: ludwig/ludwig/experiment.py
imports: import argparse
  import logging
  import os
  import sys
  from typing import List, Optional, Union
  import pandas
  from ludwig.api import kfold_cross_validate, LudwigModel
  from ludwig.backend import ALL_BACKENDS, Backend, initialize_backend
  from ludwig.callbacks import Callback
  from ludwig.constants import CONTINUE_PROMPT, FULL, HYPEROPT, HYPEROPT_WARNING, TEST, TRAINING, VALIDATION
  from ludwig.contrib import add_contrib_callback_args
  from ludwig.globals import LUDWIG_VERSION
  from ludwig.utils.data_utils import load_config_from_str, load_yaml, save_json
  from ludwig.utils.defaults import default_random_seed
  from ludwig.utils.print_utils import get_logging_level_registry, print_ludwig, query_yes_no
label_desc: Use image node_id 3 for calling a global function with example usage: cli(sys_argv) without return types