code: def get_input_tensors(
      model: LudwigModel,
      input_set: pd.DataFrame,
      run_config: ExplanationRunConfig,
  ) -> List[torch.Tensor]:
      """Convert the input data into a list of variables, one for each input feature.
  
      # Inputs
  
      :param model: The LudwigModel to use for encoding.
      :param input_set: The input data to encode of shape [batch size, num input features].
  
      # Return
  
      :return: A list of variables, one for each input feature. Shape of each variable is [batch size, embedding size].
      """
      # Ignore sample_ratio and sample_size from the model config, since we want to explain all the data.
      sample_ratio_bak = model.config_obj.preprocessing.sample_ratio
      sample_size_bak = model.config_obj.preprocessing.sample_size
      model.config_obj.preprocessing.sample_ratio = 1.0
      model.config_obj.preprocessing.sample_size = None
  
      config = model.config_obj.to_dict()
      training_set_metadata = copy.deepcopy(model.training_set_metadata)
      for feature in config[INPUT_FEATURES]:
          preprocessing = training_set_metadata[feature[NAME]][
              PREPROCESSING
          ]
          if preprocessing.get("cache_encoder_embeddings"):
              preprocessing["cache_encoder_embeddings"] = False
  
      # Convert raw input data into preprocessed tensor data
      dataset, _ = preprocess_for_prediction(
          config,
          dataset=input_set,
          training_set_metadata=training_set_metadata,
          data_format="auto",
          split="full",
          include_outputs=False,
          backend=model.backend,
          callbacks=model.callbacks,
      )
  
      # Restore sample_ratio and sample_size
      model.config_obj.preprocessing.sample_ratio = sample_ratio_bak
      model.config_obj.preprocessing.sample_size = sample_size_bak
  
      # Make sure the number of rows in the preprocessed dataset matches the number of rows in the input data
      assert (
          dataset.to_df().shape[0] == input_set.shape[0]
      ), f"Expected {input_set.shape[0]} rows in preprocessed dataset, but got {dataset.to_df().shape[0]}"
  
      # Convert dataset into a dict of tensors, and split each tensor into batches to control GPU memory usage
      inputs = {
          name: torch.from_numpy(
              dataset.dataset[feature.proc_column]
          ).split(run_config.batch_size)
          for name, feature in model.model.input_features.items()
      }
  
      # Dict of lists to list of dicts
      input_batches = [
          dict(zip(inputs, t)) for t in zip(*inputs.values())
      ]
  
      # List of dicts to dict of lists
      preproc_inputs = {
          k: torch.cat([d[k] for d in input_batches])
          for k in input_batches[0]
      }
  
      data_to_predict = [v for _, v in preproc_inputs.items()]
      tensors = []
      for t in data_to_predict:
          # TODO(travis): Consider changing to `if not torch.is_floating_point(t.dtype)` to simplify, then handle bool
          # case in this block.
          if (
              t.dtype == torch.int8
              or t.dtype == torch.int16
              or t.dtype == torch.int32
              or t.dtype == torch.int64
          ):
              # Don't wrap input into a variable if it's an integer type, since it will be used as an index into the
              # embedding table. We explain the output of the embedding table, not the input to the embedding table using
              # LayerIntegratedGradients.
              tensors.append(t)
          else:
              # Wrap input into a variable so torch will track the gradient and LayerIntegratedGradients can explain it.
              if t.dtype == torch.bool:
                  t = t.to(torch.float32)
              tensors.append(Variable(t, requires_grad=True))
  
      return tensors
  
imports: import copy
  import gc
  import logging
  from collections import defaultdict
  from dataclasses import dataclass
  from typing import Dict, List, Optional, Tuple
  import numpy
  import numpy.typing
  import pandas
  import torch
  from captum.attr import LayerIntegratedGradients, TokenReferenceBase
  from captum.attr._utils.input_layer_wrapper import InputIdentity
  from torch.autograd import Variable
  from tqdm import tqdm
  from ludwig.api import LudwigModel
  from ludwig.api_annotations import PublicAPI
  from ludwig.constants import BINARY, CATEGORY, DATE, IMAGE, INPUT_FEATURES, MINIMUM_BATCH_SIZE, NAME, NUMBER, PREPROCESSING, SEQUENCE, SET, TEXT, UNKNOWN_SYMBOL
  from ludwig.data.preprocessing import preprocess_for_prediction
  from ludwig.explain.explainer import Explainer
  from ludwig.explain.explanation import ExplanationsResult
  from ludwig.explain.util import get_pred_col, replace_layer_with_copy
  from ludwig.features.feature_utils import LudwigFeatureDict
  from ludwig.models.ecd import ECD
  from ludwig.utils.torch_utils import DEVICE
label_desc: Use image node_id 2 for calling a global function with example usage: get_input_tensors(model, input_set, run_config) and returns: tensors