code: def run_api_experiment_separated_datasets(
      input_features, output_features, data_csv
  ):
      """Helper method to avoid code repetition in running an experiment.
  
      :param input_features: input schema
      :param output_features: output schema
      :param data_csv: path to data
      :return: None
      """
      config = {
          "input_features": input_features,
          "output_features": output_features,
          "combiner": {"type": "concat", "output_size": 14},
          TRAINER: {"epochs": 2, BATCH_SIZE: 128},
      }
  
      model = LudwigModel(config)
  
      # Training with dataframe
      data_df = read_csv(data_csv)
      train_df = data_df.sample(frac=0.8)
      test_df = data_df.drop(train_df.index).sample(frac=0.5)
      validation_df = data_df.drop(train_df.index).drop(test_df.index)
  
      basename, ext = os.path.splitext(data_csv)
      train_fname = basename + ".train" + ext
      val_fname = basename + ".validation" + ext
      test_fname = basename + ".test" + ext
      output_dirs = []
  
      try:
          train_df.to_csv(train_fname)
          validation_df.to_csv(val_fname)
          test_df.to_csv(test_fname)
  
          # Training with csv
          _, _, output_dir = model.train(
              training_set=train_fname,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, _, output_dir = model.train(
              training_set=train_fname,
              validation_set=val_fname,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, _, output_dir = model.train(
              training_set=train_fname,
              validation_set=val_fname,
              test_set=test_fname,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, output_dir = model.predict(dataset=test_fname)
          output_dirs.append(output_dir)
  
      finally:
          # Remove results/intermediate data saved to disk
          os.remove(train_fname)
          os.remove(val_fname)
          os.remove(test_fname)
          for output_dir in output_dirs:
              shutil.rmtree(output_dir, ignore_errors=True)
  
      output_dirs = []
      try:
          _, _, output_dir = model.train(
              training_set=train_df,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, _, output_dir = model.train(
              training_set=train_df,
              validation_set=validation_df,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, _, output_dir = model.train(
              training_set=train_df,
              validation_set=validation_df,
              test_set=test_df,
              skip_save_processed_input=True,
              skip_save_progress=True,
              skip_save_unprocessed_output=True,
          )
          output_dirs.append(output_dir)
  
          _, output_dir = model.predict(dataset=data_df)
          output_dirs.append(output_dir)
  
      finally:
          for output_dir in output_dirs:
              shutil.rmtree(output_dir, ignore_errors=True)
  
imports: import json
  import os
  import shutil
  from unittest import mock
  import pandas
  import pytest
  import torch
  import yaml
  from ludwig.api import LudwigModel
  from ludwig.callbacks import Callback
  from ludwig.constants import BATCH_SIZE, ENCODER, TRAINER, TYPE
  from ludwig.globals import MODEL_HYPERPARAMETERS_FILE_NAME
  from ludwig.models.inference import InferenceModule
  from ludwig.utils.data_utils import read_csv
  from tests.integration_tests.utils import category_feature, ENCODERS, generate_data, get_weights, image_feature, run_api_experiment, sequence_feature, text_feature
label_desc: Use image node_id 1 for calling a global function with example usage: run_api_experiment_separated_datasets(input_features, output_features, data_csv) without return types