code: def _upgrade_legacy_image_encoders(
      feature: FeatureConfigDict,
  ) -> FeatureConfigDict:
      if feature.get(TYPE) != IMAGE:
          return feature
  
      encoder_mapping = {
          "resnet": "_resnet_legacy",
          "vit": "_vit_legacy",
      }
  
      encoder = feature.get(ENCODER, {})
      encoder_type = encoder.get(TYPE)
      if encoder_type not in encoder_mapping:
          return feature
  
      # For this version of Ludwig, only ECD supported these encoders.
      new_encoder_cls = get_encoder_cls(
          MODEL_ECD, feature[TYPE], encoder_type
      )
      new_encoder_fields = new_encoder_cls.get_valid_field_names()
  
      legacy_encoder_cls = get_encoder_cls(
          MODEL_ECD, feature[TYPE], encoder_mapping[encoder_type]
      )
      legacy_encoder_fields = legacy_encoder_cls.get_valid_field_names()
  
      user_fields = set(encoder.keys())
      user_fields.remove(TYPE)
  
      removed_fields = legacy_encoder_fields.difference(
          new_encoder_fields
      )
      added_fields = new_encoder_fields.difference(
          legacy_encoder_fields
      )
  
      user_legacy_fields = user_fields.intersection(removed_fields)
      user_new_fields = user_fields.intersection(added_fields)
      if len(user_legacy_fields) > 0:
          if len(user_new_fields) > 0:
              raise ValueError(
                  f"Intended encoder type is ambiguous. "
                  f"Provided encoder fields matching encoder '{encoder_type}' {user_new_fields} and "
                  f"legacy encoder '{encoder_mapping[encoder_type]}' {user_legacy_fields}. "
                  f"Please remove features unique to one of these encoder types from your configuration."
              )
  
          warnings.warn(
              f"Encoder '{encoder_type}' with params '{user_legacy_fields}' has been renamed to "
              f"'{encoder_mapping[encoder_type]}'. Please upgrade your config to use the new '{encoder_type}' as "
              f"support for '{encoder_mapping[encoder_type]}' is not guaranteed past v0.8.",
              DeprecationWarning,
          )
  
          # User provided legacy fields and no new fields, so we assume they intended to use the legacy encoder
          encoder[TYPE] = encoder_mapping[encoder_type]
  
      return feature
  
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 24 for calling a global function with example usage: _upgrade_legacy_image_encoders(feature) and returns: feature, feature, feature