code: def _upgrade_hyperopt(
      hyperopt: HyperoptConfigDict,
  ) -> HyperoptConfigDict:
      """Upgrades hyperopt config (in-place)"""
      # check for use of legacy "training" reference, if any found convert to "trainer"
      if PARAMETERS in hyperopt:
          hparams = hyperopt[PARAMETERS]
          for k, v in list(hparams.items()):
              substr = "training."
              if k.startswith(substr):
                  warnings.warn(
                      'Config section "training" renamed to "trainer" and will be removed in v0.6',
                      DeprecationWarning,
                  )
                  hparams["trainer." + k[len(substr) :]] = v
                  del hparams[k]
  
      # check for legacy parameters in "executor"
      if EXECUTOR in hyperopt:
          hpexecutor = hyperopt[EXECUTOR]
          executor_type = hpexecutor.get(TYPE, None)
          if executor_type is not None and executor_type != RAY:
              warnings.warn(
                  f'executor type "{executor_type}" not supported, converted to "ray" will be flagged as error '
                  "in v0.6",
                  DeprecationWarning,
              )
              hpexecutor[TYPE] = RAY
  
          # if search_alg not at top level and is present in executor, promote to top level
          if SEARCH_ALG in hpexecutor:
              # promote only if not in top-level, otherwise use current top-level
              if SEARCH_ALG not in hyperopt:
                  hyperopt[SEARCH_ALG] = hpexecutor[SEARCH_ALG]
                  if isinstance(hyperopt[SEARCH_ALG], str):
                      hyperopt[SEARCH_ALG] = {
                          TYPE: hyperopt[SEARCH_ALG]
                      }
              del hpexecutor[SEARCH_ALG]
      else:
          warnings.warn(
              'Missing "executor" section, adding "ray" executor will be flagged as error in v0.6',
              DeprecationWarning,
          )
          hyperopt[EXECUTOR] = {TYPE: RAY}
  
      # check for legacy "sampler" section
      if SAMPLER in hyperopt:
          warnings.warn(
              f'"{SAMPLER}" is no longer supported, converted to "{SEARCH_ALG}". "{SAMPLER}" will be flagged as '
              "error in v0.6",
              DeprecationWarning,
          )
          if SEARCH_ALG in hyperopt[SAMPLER]:
              if SEARCH_ALG not in hyperopt:
                  hyperopt[SEARCH_ALG] = hyperopt[SAMPLER][SEARCH_ALG]
                  if isinstance(hyperopt[SEARCH_ALG], str):
                      hyperopt[SEARCH_ALG] = {
                          TYPE: hyperopt[SEARCH_ALG]
                      }
                  warnings.warn(
                      'Moved "search_alg" to hyperopt config top-level',
                      DeprecationWarning,
                  )
  
          # if num_samples or scheduler exist in SAMPLER move to EXECUTOR Section
          if (
              NUM_SAMPLES in hyperopt[SAMPLER]
              and NUM_SAMPLES not in hyperopt[EXECUTOR]
          ):
              hyperopt[EXECUTOR][NUM_SAMPLES] = hyperopt[SAMPLER][
                  NUM_SAMPLES
              ]
              warnings.warn(
                  'Moved "num_samples" from "sampler" to "executor"',
                  DeprecationWarning,
              )
  
          if (
              SCHEDULER in hyperopt[SAMPLER]
              and SCHEDULER not in hyperopt[EXECUTOR]
          ):
              hyperopt[EXECUTOR][SCHEDULER] = hyperopt[SAMPLER][
                  SCHEDULER
              ]
              warnings.warn(
                  'Moved "scheduler" from "sampler" to "executor"',
                  DeprecationWarning,
              )
  
          if (
              SCHEDULER in hyperopt[EXECUTOR]
              and len(hyperopt[EXECUTOR][SCHEDULER].keys()) == 0
          ):
              del hyperopt[EXECUTOR][SCHEDULER]
  
          # remove legacy section
          del hyperopt[SAMPLER]
  
      if SEARCH_ALG not in hyperopt:
          # make top-level as search_alg, if missing put in default value
          hyperopt[SEARCH_ALG] = {TYPE: "variant_generator"}
          warnings.warn(
              'Missing "search_alg" at hyperopt top-level, adding in default value, will be flagged as error '
              "in v0.6",
              DeprecationWarning,
          )
      return hyperopt
  
imports: import copy
  import logging
  import warnings
  from typing import Any, Callable, Dict, List, Union
  from ludwig.api_annotations import DeveloperAPI
  from ludwig.constants import AUDIO, BIAS, CLASS_WEIGHTS, COLUMN, CONV_BIAS, CONV_USE_BIAS, DECODER, DEFAULT_BIAS, DEFAULT_USE_BIAS, DEFAULTS, ENCODER, EVAL_BATCH_SIZE, EXECUTOR, FORCE_SPLIT, HEIGHT, HYPEROPT, IMAGE, INPUT_FEATURES, LOSS, MISSING_VALUE_STRATEGY, MODEL_ECD, MODEL_GBM, MODEL_TYPE, NAME, NUM_SAMPLES, NUMBER, OUTPUT_FEATURES, PARAMETERS, PREPROCESSING, PROBABILITIES, RANDOM, RAY, SAMPLER, SCHEDULER, SEARCH_ALG, SEQUENCE, SPLIT, SPLIT_PROBABILITIES, STRATIFY, TEXT, TIMESERIES, TRAINER, TRAINING, TYPE, USE_BIAS, WIDTH
  from ludwig.features.feature_registries import get_base_type_registry, get_input_type_registry, get_output_type_registry
  from ludwig.globals import LUDWIG_VERSION
  from ludwig.schema.defaults.gbm import GBMDefaultsConfig
  from ludwig.schema.encoders.utils import get_encoder_cls
  from ludwig.types import FeatureConfigDict, FeatureTypeDefaultsDict, HyperoptConfigDict, ModelConfigDict, PreprocessingConfigDict, TrainerConfigDict, TrainingSetMetadataDict
  from ludwig.utils.metric_utils import TrainerMetric
  from ludwig.utils.misc_utils import get_from_registry, merge_dict
  from ludwig.utils.version_transformation import VersionTransformation, VersionTransformationRegistry
label_desc: Use image node_id 15 for calling a global function with example usage: _upgrade_hyperopt(hyperopt) and returns: hyperopt