code: def from_dict(config: ModelConfigDict) -> "ModelConfig":
      config = copy.deepcopy(config)
      config = upgrade_config_dict_to_latest_version(config)
  
      # Use sanitized feature names.
      # NOTE: This must be kept consistent with build_dataset()
      for input_feature in config[INPUT_FEATURES]:
          input_feature[NAME] = get_sanitized_feature_name(
              input_feature[NAME]
          )
          if COLUMN in input_feature and input_feature[COLUMN]:
              input_feature[COLUMN] = get_sanitized_feature_name(
                  input_feature[COLUMN]
              )
      for output_feature in config[OUTPUT_FEATURES]:
          output_feature[NAME] = get_sanitized_feature_name(
              output_feature[NAME]
          )
          if COLUMN in output_feature and output_feature[COLUMN]:
              output_feature[COLUMN] = get_sanitized_feature_name(
                  output_feature[COLUMN]
              )
  
      # Sanitize tied feature names.
      for input_feature in config[INPUT_FEATURES]:
          if TIED in input_feature and input_feature[TIED]:
              input_feature[TIED] = get_sanitized_feature_name(
                  input_feature[TIED]
              )
  
      # Sanitize dependent feature names.
      for output_feature in config[OUTPUT_FEATURES]:
          if (
              DEPENDENCIES in output_feature
              and output_feature[DEPENDENCIES]
          ):
              output_feature[DEPENDENCIES] = [
                  get_sanitized_feature_name(feature_name)
                  for feature_name in output_feature[DEPENDENCIES]
              ]
  
      config["model_type"] = config.get("model_type", MODEL_ECD)
      model_type = config["model_type"]
      if model_type not in model_type_schema_registry:
          raise ValidationError(
              f"Invalid model type: '{model_type}', expected one of: {list(model_type_schema_registry.keys())}"
          )
  
      config = merge_with_defaults(config)
  
      # TODO(travis): handle this with helper function
      backend = config.get(BACKEND)
      if isinstance(backend, str):
          config[BACKEND] = {"type": backend}
  
      # JSON schema validation. Note that this is desireable on top of `schema.load(config)` below because marshmallow
      # deserialization permits additional properties while JSON schema validation, for schema (e.g. `trainer`) that
      # have `additionalProperties=False`, does not.
      #
      # Illustrative example: test_validate_config_misc.py::test_validate_no_trainer_type
      #
      # TODO: Set `additionalProperties=False` for all Ludwig schema, and look into passing in `unknown='RAISE'` to
      # marshmallow.load(), which raises an error for unknown fields during deserialization.
      # https://marshmallow.readthedocs.io/en/stable/marshmallow.schema.html#marshmallow.schema.Schema.load
      check_schema(config)
  
      cls = model_type_schema_registry[model_type]
      schema = cls.get_class_schema()()
      try:
          config_obj: ModelConfig = schema.load(config)
      except ValidationError as e:
          raise ConfigValidationError(
              f"Config validation error raised during config deserialization: {e}"
          ) from e
  
      return config_obj
  
imports: import copy
  from abc import ABC
  from typing import Any, Dict, Optional, Set
  from marshmallow import ValidationError
  from ludwig.api_annotations import DeveloperAPI
  from ludwig.config_validation.checks import get_config_check_registry
  from ludwig.config_validation.validation import check_schema
  from ludwig.constants import BACKEND, COLUMN, DEPENDENCIES, ENCODER, INPUT_FEATURES, MODEL_ECD, NAME, OUTPUT_FEATURES, TIED
  from ludwig.error import ConfigValidationError
  from ludwig.globals import LUDWIG_VERSION
  from ludwig.schema import utils
  from ludwig.schema.defaults.base import BaseDefaultsConfig
  from ludwig.schema.features.base import BaseInputFeatureConfig, BaseOutputFeatureConfig, FeatureCollection
  from ludwig.schema.hyperopt import HyperoptConfig
  from ludwig.schema.model_types.utils import merge_fixed_preprocessing_params, merge_with_defaults, sanitize_and_filter_combiner_entities_, set_derived_feature_columns_, set_hyperopt_defaults_, set_llm_parameters, set_preprocessing_parameters, set_tagger_decoder_parameters, set_validation_parameters
  from ludwig.schema.preprocessing import PreprocessingConfig
  from ludwig.schema.trainer import BaseTrainerConfig
  from ludwig.schema.utils import ludwig_dataclass
  from ludwig.types import ModelConfigDict
  from ludwig.utils.backward_compatibility import upgrade_config_dict_to_latest_version
  from ludwig.utils.data_utils import get_sanitized_feature_name, load_yaml
  from ludwig.utils.registry import Registry
label_desc: Use image node_id 2 for calling the ModelConfig obj's underlying member method code with example usage: obj.from_dict(config) and returns: config_obj