code: def test_hyperopt_with_feature_specific_parameters(
      csv_filename, tmpdir, ray_cluster_7cpu
  ):
      input_features = [
          text_feature(name="utterance", reduce_output="sum"),
          category_feature(vocab_size=3),
      ]
  
      output_features = [
          category_feature(vocab_size=3, output_feature=True)
      ]
  
      rel_path = generate_data(
          input_features, output_features, csv_filename
      )
  
      filter_size_search_space = [5, 7]
      embedding_size_search_space = [4, 8, 12]
  
      config = {
          INPUT_FEATURES: input_features,
          OUTPUT_FEATURES: output_features,
          COMBINER: {TYPE: "concat", "num_fc_layers": 2},
          TRAINER: {
              "epochs": 1,
              "learning_rate": 0.001,
              BATCH_SIZE: 128,
          },
          HYPEROPT: {
              "parameters": {
                  input_features[0][NAME]
                  + ".encoder.filter_size": {
                      "space": "choice",
                      "categories": filter_size_search_space,
                  },
                  input_features[1][NAME]
                  + ".encoder.embedding_size": {
                      "space": "choice",
                      "categories": embedding_size_search_space,
                  },
              },
              "goal": "minimize",
              "output_feature": output_features[0][NAME],
              "validation_metrics": "loss",
              "executor": {TYPE: "ray", "num_samples": 1},
              "search_alg": {TYPE: "variant_generator"},
          },
      }
  
      hyperopt_results = hyperopt(
          config,
          dataset=rel_path,
          output_directory=tmpdir,
          experiment_name="test_hyperopt",
      )
      hyperopt_results_df = (
          hyperopt_results.experiment_analysis.results_df
      )
  
      model_parameters = json.load(
          open(
              os.path.join(
                  hyperopt_results_df.iloc[0]["trial_dir"],
                  "test_hyperopt_run",
                  "model",
                  "model_hyperparameters.json",
              )
          )
      )
  
      for input_feature in model_parameters[INPUT_FEATURES]:
          if input_feature[TYPE] == TEXT:
              assert (
                  input_feature["encoder"]["filter_size"]
                  in filter_size_search_space
              )
          elif input_feature[TYPE] == CATEGORY:
              assert (
                  input_feature["encoder"]["embedding_size"]
                  in embedding_size_search_space
              )
  
imports: import json
  import os
  import os.path
  import uuid
  from typing import Dict, Tuple
  import pytest
  from ludwig.backend import initialize_backend
  from ludwig.constants import ACCURACY, AUTO, BATCH_SIZE, CATEGORY, COMBINER, EXECUTOR, HYPEROPT, INPUT_FEATURES, MAX_CONCURRENT_TRIALS, MODEL_ECD, MODEL_GBM, MODEL_TYPE, NAME, OUTPUT_FEATURES, RAY, TEST, TEXT, TRAINER, TRAINING, TYPE, VALIDATION
  from ludwig.globals import HYPEROPT_STATISTICS_FILE_NAME
  from ludwig.hyperopt.results import HyperoptResults
  from ludwig.hyperopt.run import hyperopt
  from ludwig.hyperopt.utils import update_hyperopt_params_with_defaults
  from ludwig.schema.model_config import ModelConfig
  from ludwig.utils import fs_utils
  from ludwig.utils.data_utils import load_json, use_credentials
  from tests.integration_tests.utils import category_feature, generate_data, minio_test_creds, private_param, remote_tmpdir, text_feature
  from ludwig.hyperopt.execution import get_build_hyperopt_executor, RayTuneExecutor
label_desc: Use image node_id 9 for calling a global function with example usage: test_hyperopt_with_feature_specific_parameters(csv_filename, tmpdir, ray_cluster_7cpu) without return types