class_docstr: A single-task variational GP model following [hensman2013svgp]_.
  
  By default, the inducing points are initialized though the
  `GreedyVarianceReduction` of [burt2020svgp]_, which is known to be
  effective for building globally accurate models. However, custom
  inducing point allocators designed for specific down-stream tasks can also be
  provided (see [moss2023ipa]_ for details), e.g. `GreedyImprovementReduction`
  when the goal is to build a model suitable for standard BO.
  
  A single-task variational GP using relatively strong priors on the Kernel
  hyperparameters, which work best when covariates are normalized to the unit
  cube and outcomes are standardized (zero mean, unit variance).
  
  This model works in batch mode (each batch having its own hyperparameters).
  When the training observations include multiple outputs, this model will use
  batching to model outputs independently. However, batches of multi-output models
  are not supported at this time, if you need to use those, please use a
  ModelListGP.
  
  Use this model if you have a lot of data or if your responses are non-Gaussian.
  
  To train this model, you should use gpytorch.mlls.VariationalELBO and not
  the exact marginal log likelihood.
  
  Example:
      >>> import torch
      >>> from botorch.models import SingleTaskVariationalGP
      >>> from gpytorch.mlls import VariationalELBO
      >>>
      >>> train_X = torch.rand(20, 2)
      >>> model = SingleTaskVariationalGP(train_X)
      >>> mll = VariationalELBO(
      >>>     model.likelihood, model.model, num_data=train_X.shape[-2]
      >>> )
docstr: Args:
      train_X: Training inputs (due to the ability of the SVGP to sub-sample
          this does not have to be all of the training inputs).
      train_Y: Training targets (optional).
      likelihood: Instance of a GPyTorch likelihood. If omitted, uses a
          either a `GaussianLikelihood` (if `num_outputs=1`) or a
          `MultitaskGaussianLikelihood`(if `num_outputs>1`).
      num_outputs: Number of output responses per input (default: 1).
      covar_module: Kernel function. If omitted, uses a `MaternKernel`.
      mean_module: Mean of GP model. If omitted, uses a `ConstantMean`.
      variational_distribution: Type of variational distribution to use
          (default: CholeskyVariationalDistribution), the properties of the
          variational distribution will encourage scalability or ease of
          optimization.
      variational_strategy: Type of variational strategy to use (default:
          VariationalStrategy). The default setting uses "whitening" of the
          variational distribution to make training easier.
      inducing_points: The number or specific locations of the inducing points.
      inducing_point_allocator: The `InducingPointAllocator` used to
          initialize the inducing point locations. If omitted,
          uses `GreedyVarianceReduction`.
code: def __init__(
      self,
      train_X: Tensor,
      train_Y: Optional[Tensor] = None,
      likelihood: Optional[Likelihood] = None,
      num_outputs: int = 1,
      learn_inducing_points: bool = True,
      covar_module: Optional[Kernel] = None,
      mean_module: Optional[Mean] = None,
      variational_distribution: Optional[
          _VariationalDistribution
      ] = None,
      variational_strategy: Type[
          _VariationalStrategy
      ] = VariationalStrategy,
      inducing_points: Optional[Union[Tensor, int]] = None,
      outcome_transform: Optional[OutcomeTransform] = None,
      input_transform: Optional[InputTransform] = None,
      inducing_point_allocator: Optional[InducingPointAllocator] = None,
  ) -> None:
      r"""
      Args:
          train_X: Training inputs (due to the ability of the SVGP to sub-sample
              this does not have to be all of the training inputs).
          train_Y: Training targets (optional).
          likelihood: Instance of a GPyTorch likelihood. If omitted, uses a
              either a `GaussianLikelihood` (if `num_outputs=1`) or a
              `MultitaskGaussianLikelihood`(if `num_outputs>1`).
          num_outputs: Number of output responses per input (default: 1).
          covar_module: Kernel function. If omitted, uses a `MaternKernel`.
          mean_module: Mean of GP model. If omitted, uses a `ConstantMean`.
          variational_distribution: Type of variational distribution to use
              (default: CholeskyVariationalDistribution), the properties of the
              variational distribution will encourage scalability or ease of
              optimization.
          variational_strategy: Type of variational strategy to use (default:
              VariationalStrategy). The default setting uses "whitening" of the
              variational distribution to make training easier.
          inducing_points: The number or specific locations of the inducing points.
          inducing_point_allocator: The `InducingPointAllocator` used to
              initialize the inducing point locations. If omitted,
              uses `GreedyVarianceReduction`.
      """
      with torch.no_grad():
          transformed_X = self.transform_inputs(
              X=train_X, input_transform=input_transform
          )
      if train_Y is not None:
          if outcome_transform is not None:
              train_Y, _ = outcome_transform(train_Y)
          self._validate_tensor_args(X=transformed_X, Y=train_Y)
          validate_input_scaling(train_X=transformed_X, train_Y=train_Y)
          if train_Y.shape[-1] != num_outputs:
              num_outputs = train_Y.shape[-1]
  
      self._num_outputs = num_outputs
      self._input_batch_shape = train_X.shape[:-2]
      aug_batch_shape = copy.deepcopy(self._input_batch_shape)
      if num_outputs > 1:
          aug_batch_shape += torch.Size([num_outputs])
      self._aug_batch_shape = aug_batch_shape
  
      if likelihood is None:
          if num_outputs == 1:
              likelihood = get_gaussian_likelihood_with_gamma_prior(
                  batch_shape=self._aug_batch_shape
              )
          else:
              likelihood = MultitaskGaussianLikelihood(
                  num_tasks=num_outputs
              )
      else:
          self._is_custom_likelihood = True
  
      if learn_inducing_points and (
          inducing_point_allocator is not None
      ):
          warnings.warn(
              "After all the effort of specifying an inducing point allocator, "
              "you probably want to stop the inducing point locations "
              "being further optimized during the model fit. If so "
              "then set `learn_inducing_points` to False.",
              UserWarning,
          )
  
      if inducing_point_allocator is None:
          self._inducing_point_allocator = GreedyVarianceReduction()
      else:
          self._inducing_point_allocator = inducing_point_allocator
  
      model = _SingleTaskVariationalGP(
          train_X=transformed_X,
          num_outputs=num_outputs,
          learn_inducing_points=learn_inducing_points,
          covar_module=covar_module,
          mean_module=mean_module,
          variational_distribution=variational_distribution,
          variational_strategy=variational_strategy,
          inducing_points=inducing_points,
          inducing_point_allocator=self._inducing_point_allocator,
      )
  
      super().__init__(
          model=model, likelihood=likelihood, num_outputs=num_outputs
      )
  
      if outcome_transform is not None:
          self.outcome_transform = outcome_transform
      if input_transform is not None:
          self.input_transform = input_transform
  
      # for model fitting utilities
      # TODO: make this a flag?
      self.model.train_inputs = [transformed_X]
      if train_Y is not None:
          self.model.train_targets = train_Y.squeeze(-1)
  
      self.to(train_X)
  
imports: from __future__ import annotations
  import copy
  import warnings
  from typing import Optional, Type, TypeVar, Union
  import torch
  from botorch.models.gpytorch import GPyTorchModel
  from botorch.models.transforms.input import InputTransform
  from botorch.models.transforms.outcome import OutcomeTransform
  from botorch.models.utils import validate_input_scaling
  from botorch.models.utils.gpytorch_modules import get_gaussian_likelihood_with_gamma_prior, get_matern_kernel_with_gamma_prior
  from botorch.models.utils.inducing_point_allocators import GreedyVarianceReduction, InducingPointAllocator
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from gpytorch.distributions import MultivariateNormal
  from gpytorch.kernels import Kernel
  from gpytorch.likelihoods import GaussianLikelihood, Likelihood, MultitaskGaussianLikelihood
  from gpytorch.means import ConstantMean, Mean
  from gpytorch.models import ApproximateGP
  from gpytorch.utils.memoize import clear_cache_hook
  from gpytorch.variational import _VariationalDistribution, _VariationalStrategy, CholeskyVariationalDistribution, IndependentMultitaskVariationalStrategy, VariationalStrategy
  from torch import Tensor
  from torch.nn import Module
label_desc: Use image node_id 1 to create a new SingleTaskVariationalGP object from inherited base classes: ApproximateGPyTorchModel with example: obj = SingleTaskVariationalGP(train_X, train_Y, likelihood, num_outputs, learn_inducing_points, covar_module, mean_module, variational_distribution, variational_strategy, inducing_points, outcome_transform, input_transform, inducing_point_allocator)