code: def __init__(
      self,
      feature_configs: List[FeatureConfigDict],
      metadata: TrainingSetMetadataDict,
  ):
      super().__init__()
  
      self.input_features = LudwigFeatureDict()
  
      input_feature_configs = []
      for feature in feature_configs:
          feature_cls = get_from_registry(
              feature[TYPE], get_input_type_registry()
          )
  
          # TODO(travis): this assumes ECD is the selected model type, which is not problematic for now, as
          # the only thing GBM vs ECD changes is the default encoder, but luckily at this point the encoder types
          # have been fully materialized. However, this could change in the future as ECD and GBM feature configs
          # diverge, so we should find a way to remove this. The best solution is to the change the input params from
          # FeatureConfigDict types to BaseInputFeatureConfig types, which will require a refactor of preprocessing to
          # use the schema, not the dict types.
          feature_obj = get_input_feature_cls(
              MODEL_ECD, feature[TYPE]
          ).from_dict(feature)
          feature_cls.update_config_with_metadata(
              feature_obj, metadata[feature[NAME]]
          )
  
          # When running prediction or eval, we need the preprocessing to use the original pretrained
          # weights, which requires unsetting this field. In the future, we could avoid this by plumbing
          # through the saved weights and loading them dynamically after building the model.
          feature_obj.encoder.saved_weights_in_checkpoint = False
  
          input_feature_configs.append(feature_obj)
  
      feature_collection = FeatureCollection[BaseInputFeatureConfig](
          input_feature_configs
      )
      try:
          self.input_features.update(
              BaseModel.build_inputs(
                  input_feature_configs=feature_collection
              )
          )
      except KeyError as e:
          raise KeyError(
              f"An input feature has a name that conflicts with a class attribute of torch's ModuleDict: {e}"
          )
  
imports: from typing import Callable, Dict, List
  import numpy
  import pandas
  import torch
  from ludwig.api_annotations import DeveloperAPI
  from ludwig.constants import ENCODER_OUTPUT, MODEL_ECD, NAME, PROC_COLUMN, TYPE
  from ludwig.features.feature_registries import get_input_type_registry
  from ludwig.features.feature_utils import LudwigFeatureDict
  from ludwig.models.base import BaseModel
  from ludwig.schema.features.base import BaseInputFeatureConfig, FeatureCollection
  from ludwig.schema.features.utils import get_input_feature_cls
  from ludwig.types import FeatureConfigDict, TrainingSetMetadataDict
  from ludwig.utils.batch_size_tuner import BatchSizeEvaluator
  from ludwig.utils.dataframe_utils import from_numpy_dataset
  from ludwig.utils.misc_utils import get_from_registry
  from ludwig.utils.torch_utils import get_torch_device, LudwigModule
label_desc: Use image node_id 1 to create a new Embedder object from inherited base classes: LudwigModule with example: obj = Embedder(feature_configs, metadata)