code: def test_optimizers(optimizer_type, tmp_path):
      if (optimizer_type in {"lars", "lamb", "lion"}) and (
          not torch.cuda.is_available()
          or torch.cuda.device_count() == 0
      ):
          pytest.skip(
              "Skip: lars, lamb, and lion optimizers require GPU and none are available."
          )
  
      if ("paged" in optimizer_type or "8bit" in optimizer_type) and (
          not torch.cuda.is_available()
          or torch.cuda.device_count() == 0
      ):
          pytest.skip(
              "Skip: paged and 8-bit optimizers require GPU and none are available."
          )
  
      (
          input_features,
          output_features,
      ) = synthetic_test_data.get_feature_configs()
  
      config = {
          "input_features": input_features,
          "output_features": output_features,
          "combiner": {"type": "concat"},
          TRAINER: {
              "epochs": 5,
              "batch_size": 16,
              "evaluate_training_set": True,
              "optimizer": {"type": optimizer_type},
          },
      }
  
      # special handling for adadelta and lbfgs, break out of local minima
      if optimizer_type == "adadelta":
          config[TRAINER]["learning_rate"] = 0.1
      if optimizer_type == "lbfgs":
          config[TRAINER]["learning_rate"] = 0.05
  
      model = LudwigModel(config)
  
      # create sub-directory to store results
      results_dir = tmp_path / "results"
      results_dir.mkdir()
  
      # run experiment
      generated_data = (
          synthetic_test_data.get_generated_data_for_optimizer()
      )
      train_stats, preprocessed_data, output_directory = model.train(
          training_set=generated_data.train_df,
          output_directory=str(results_dir),
          config=config,
          skip_save_processed_input=True,
          skip_save_progress=True,
          skip_save_unprocessed_output=True,
          skip_save_model=True,
          skip_save_log=True,
      )
  
      # retrieve training losses for first and last entries.
      train_losses = train_stats[TRAINING]["combined"]["loss"]
      last_entry = len(train_losses)
  
      # ensure train loss for last entry is less than to the first entry.
      np.testing.assert_array_less(
          train_losses[last_entry - 1], train_losses[0]
      )
  
imports: import json
  import logging
  import os.path
  import re
  import numpy
  import pandas
  import pytest
  import torch
  from ludwig import globals
  from ludwig.api import LudwigModel
  from ludwig.backend import LOCAL_BACKEND
  from ludwig.constants import BATCH_SIZE, CATEGORY, DEFAULTS, EPOCHS, INPUT_FEATURES, OUTPUT_FEATURES, PREPROCESSING, TRAINER, TRAINING
  from ludwig.contribs.mlflow import MlflowCallback
  from ludwig.experiment import experiment_cli
  from ludwig.features.number_feature import numeric_transformation_registry
  from ludwig.globals import DESCRIPTION_FILE_NAME, TRAINING_PREPROC_FILE_NAME
  from ludwig.schema.optimizers import optimizer_registry
  from ludwig.utils.data_utils import load_json, replace_file_extension
  from ludwig.utils.misc_utils import get_from_registry
  from ludwig.utils.package_utils import LazyLoader
  from tests.integration_tests import synthetic_test_data
  from tests.integration_tests.utils import category_feature, generate_data, LocalTestBackend
label_desc: Use image node_id 5 for calling a global function with example usage: test_optimizers(optimizer_type, tmp_path) without return types