code: def _fit_fallback(
      mll: MarginalLogLikelihood,
      _: Type[object],
      __: Type[object],
      *,
      closure: Optional[
          Callable[[], Tuple[Tensor, Sequence[Optional[Tensor]]]]
      ] = None,
      optimizer: Optional[Callable] = fit_gpytorch_mll_scipy,
      closure_kwargs: Optional[Dict[str, Any]] = None,
      optimizer_kwargs: Optional[Dict[str, Any]] = None,
      max_attempts: int = 5,
      warning_handler: Callable[
          [WarningMessage], bool
      ] = DEFAULT_WARNING_HANDLER,
      caught_exception_types: Tuple[Type[BaseException], ...] = (
          NotPSDError,
      ),
      **ignore: Any,
  ) -> MarginalLogLikelihood:
      r"""Generic fallback method for fitting Gaussian processes.
  
      Attempts to fit a model using the provided optimizer, then determines whether or
      not to retry by evaluating a given policy on emitted warning messages. The first
      attempt is run using the initialized parameter values; subsequent attempts begin
      by resampling tunable parameters.
  
      Args:
          closure: Forward-backward closure for obtaining objective values and gradients.
              Responsible for setting parameters' `grad` attributes. If no closure is
              provided, one will be obtained by calling `get_loss_closure_with_grads`.
          optimizer: The underlying optimization algorithm to run.
          closure_kwargs: Keyword arguments passed to `closure`.
          optimizer_kwargs: Keyword arguments passed to `optimizer`.
          max_attempts: The maximum number of fit attempts allowed. The attempt budget
              is NOT shared between calls to this method.
          warning_handler: A function used to filter warnings produced when calling
              `optimizer`. Any unfiltered warnings (those for which `warning_handler`
              returns `False`) will be rethrown and trigger a model fitting retry.
          caught_exception_types: A tuple of exception types whose instances should
              be redirected to `logging.DEBUG`.
          **ignore: This function ignores unrecognized keyword arguments.
  
      Returns:
          The `mll` instance. If fitting succeeded, then `mll` will be in evaluation mode,
          i.e. `mll.training == False`. Otherwise, `mll` will be in training mode.
      """
      # Setup
      optimizer_kwargs = (
          {} if optimizer_kwargs is None else optimizer_kwargs
      )
      params_nograd: Dict[str, Parameter] = None  # pyre-ignore [9]
      ckpt_nograd: Dict[str, TensorCheckpoint] = None  # pyre-ignore [9]
      ckpt: Dict[str, TensorCheckpoint] = None  # pyre-ignore [9]
  
      # Build closure
      mll.train()
      if closure is None:
          closure = get_loss_closure_with_grads(
              mll, parameters=get_parameters(mll, requires_grad=True)
          )
      if closure_kwargs is not None:
          closure = partial(closure, **closure_kwargs)
  
      # Attempt to fit the model
      for attempt in range(1, 1 + max_attempts):
          # Wrap with rollback contextmanager so that each loop iteration reloads the
          # original state_dict upon exiting (unless we clear `ckpt`).
          with module_rollback_ctx(
              mll, checkpoint=ckpt, device=device("cpu")
          ) as ckpt:
              if attempt > 1:  # resample free parameters
                  if params_nograd is None:
                      params_nograd = get_parameters(
                          mll, requires_grad=False
                      )
  
                  if ckpt_nograd is None:  # reuse primary checkpoint
                      ckpt_nograd = {
                          name: ckpt[name] for name in params_nograd
                      }
  
                  with parameter_rollback_ctx(
                      params_nograd, checkpoint=ckpt_nograd
                  ):
                      sample_all_priors(mll.model)
  
              try:
                  # Fit the model
                  with catch_warnings(
                      record=True
                  ) as warning_list, debug(True):
                      simplefilter(
                          "always", category=OptimizationWarning
                      )
                      optimizer(
                          mll, closure=closure, **optimizer_kwargs
                      )
  
                  # Resolved warnings and determine whether or not to retry
                  done = True
                  for w in filterfalse(warning_handler, warning_list):
                      warn_explicit(
                          str(w.message),
                          w.category,
                          w.filename,
                          w.lineno,
                      )
                      done = False
  
                  if done:
                      ckpt.clear()  # do not rollback upon exiting
                      return mll.eval()
  
                  # Ensure mll is in the right mode if fitting failed
                  mll = mll if mll.training else mll.train()
                  logging.log(
                      logging.DEBUG,
                      f"Fit attempt #{attempt} of {max_attempts} triggered retry policy"
                      f"{'.' if attempt == max_attempts else '; retrying...'}",
                  )
  
              except caught_exception_types as err:
                  logging.log(
                      logging.DEBUG,
                      f"Fit attempt #{attempt} of {max_attempts} failed with exception: "
                      f"{err}",
                  )
  
      msg = "All attempts to fit the model have failed."
      if debug.off():
          msg = (
              msg
              + " For more information, try enabling botorch.settings.debug mode."
          )
  
      raise ModelFittingError(msg)
  
imports: from __future__ import annotations
  import logging
  from contextlib import nullcontext
  from functools import partial
  from itertools import filterfalse
  from typing import Any, Callable, Dict, Iterable, Optional, Sequence, Tuple, Type, Union
  from warnings import catch_warnings, simplefilter, warn, warn_explicit, WarningMessage
  from botorch.exceptions.errors import ModelFittingError, UnsupportedError
  from botorch.exceptions.warnings import OptimizationWarning
  from botorch.models.approximate_gp import ApproximateGPyTorchModel
  from botorch.models.fully_bayesian import SaasFullyBayesianSingleTaskGP
  from botorch.models.fully_bayesian_multitask import SaasFullyBayesianMultiTaskGP
  from botorch.models.model_list_gp_regression import ModelListGP
  from botorch.optim.closures import get_loss_closure_with_grads
  from botorch.optim.core import _LBFGSB_MAXITER_MAXFUN_REGEX
  from botorch.optim.fit import fit_gpytorch_mll_scipy, fit_gpytorch_mll_torch
  from botorch.optim.utils import _warning_handler_template, get_parameters, sample_all_priors
  from botorch.settings import debug
  from botorch.utils.context_managers import module_rollback_ctx, parameter_rollback_ctx, requires_grad_ctx, TensorCheckpoint
  from botorch.utils.dispatcher import Dispatcher, type_bypassing_encoder
  from gpytorch.likelihoods import Likelihood
  from gpytorch.mlls._approximate_mll import _ApproximateMarginalLogLikelihood
  from gpytorch.mlls.marginal_log_likelihood import MarginalLogLikelihood
  from gpytorch.mlls.sum_marginal_log_likelihood import SumMarginalLogLikelihood
  from linear_operator.utils.errors import NotPSDError
  from pyro.infer.mcmc import MCMC, NUTS
  from torch import device, Tensor
  from torch.nn import Parameter
  from torch.utils.data import DataLoader
label_desc: Use image node_id 5 for calling a global function with example usage: _fit_fallback(mll, _, __) and returns: mll