code: def test_custom_pyro_model(self):
      for infer_noise, dtype in itertools.product(
          (True, False), (torch.float, torch.double)
      ):
          tkwargs = {"device": self.device, "dtype": dtype}
          train_X, train_Y, train_Yvar, _ = self._get_unnormalized_data(
              infer_noise=infer_noise, **tkwargs
          )
          model = SaasFullyBayesianSingleTaskGP(
              train_X=train_X,
              train_Y=train_Y,
              train_Yvar=train_Yvar,
              pyro_model=CustomPyroModel(),
          )
          with self.assertRaisesRegex(
              NotImplementedError,
              "load_state_dict only works for SaasPyroModel",
          ):
              model.load_state_dict({})
          self.assertIsInstance(model.pyro_model, CustomPyroModel)
          self.assertAllClose(model.pyro_model.train_X, train_X)
          self.assertAllClose(model.pyro_model.train_Y, train_Y)
          if infer_noise:
              self.assertIsNone(model.pyro_model.train_Yvar)
          else:
              self.assertAllClose(
                  model.pyro_model.train_Yvar,
                  train_Yvar.clamp(MIN_INFERRED_NOISE_LEVEL),
              )
          # Use transforms
          model = SaasFullyBayesianSingleTaskGP(
              train_X=train_X,
              train_Y=train_Y,
              train_Yvar=train_Yvar,
              input_transform=Normalize(d=train_X.shape[-1]),
              outcome_transform=Standardize(m=1),
              pyro_model=CustomPyroModel(),
          )
          self.assertIsInstance(model.pyro_model, CustomPyroModel)
          lb, ub = train_X.min(dim=0).values, train_X.max(dim=0).values
          self.assertAllClose(
              model.pyro_model.train_X, (train_X - lb) / (ub - lb)
          )
          mu, sigma = train_Y.mean(dim=0), train_Y.std(dim=0)
          self.assertAllClose(
              model.pyro_model.train_Y, (train_Y - mu) / sigma
          )
          if not infer_noise:
              self.assertAllClose(
                  model.pyro_model.train_Yvar,
                  train_Yvar.clamp(MIN_INFERRED_NOISE_LEVEL)
                  / (sigma**2),
                  atol=5e-4,
              )
  
imports: import itertools
  from unittest import mock
  from unittest.mock import patch
  import pyro
  import torch
  from botorch import fit_fully_bayesian_model_nuts, utils
  from botorch.acquisition.analytic import ExpectedImprovement, PosteriorMean, ProbabilityOfImprovement, UpperConfidenceBound
  from botorch.acquisition.logei import qLogExpectedImprovement, qLogNoisyExpectedImprovement
  from botorch.acquisition.monte_carlo import qExpectedImprovement, qNoisyExpectedImprovement, qProbabilityOfImprovement, qSimpleRegret, qUpperConfidenceBound
  from botorch.acquisition.multi_objective import prune_inferior_points_multi_objective, qExpectedHypervolumeImprovement, qNoisyExpectedHypervolumeImprovement
  from botorch.acquisition.multi_objective.logei import qLogExpectedHypervolumeImprovement, qLogNoisyExpectedHypervolumeImprovement
  from botorch.acquisition.utils import prune_inferior_points
  from botorch.models import ModelList, ModelListGP
  from botorch.models.deterministic import GenericDeterministicModel
  from botorch.models.fully_bayesian import MCMC_DIM, MIN_INFERRED_NOISE_LEVEL, PyroModel, SaasFullyBayesianSingleTaskGP, SaasPyroModel
  from botorch.models.transforms import Normalize, Standardize
  from botorch.posteriors.fully_bayesian import batched_bisect, GaussianMixturePosterior
  from botorch.sampling.get_sampler import get_sampler
  from botorch.utils.datasets import SupervisedDataset
  from botorch.utils.multi_objective.box_decompositions.non_dominated import NondominatedPartitioning
  from botorch.utils.safe_math import logmeanexp
  from botorch.utils.testing import BotorchTestCase
  from gpytorch.distributions import MultivariateNormal
  from gpytorch.kernels import MaternKernel, ScaleKernel
  from gpytorch.likelihoods import FixedNoiseGaussianLikelihood, GaussianLikelihood
  from gpytorch.means import ConstantMean
  from linear_operator.operators import to_linear_operator
  from pyro.ops.integrator import _EXCEPTION_HANDLERS, potential_grad, register_exception_handler
label_desc: Use image node_id 11 for calling the TestFullyBayesianSingleTaskGP obj's underlying member method code with example usage: obj.test_custom_pyro_model() without return types