class_docstr: Base class for batched multi-output GPyTorch models with independent outputs.
  
  This model should be used when the same training data is used for all outputs.
  Outputs are modeled independently by using a different batch for each output.
  
  :meta private:
class_docstr_tok: ["Base","class","for","batched","multi-output","GPyTorch","models","with","independent","outputs",".","This","model","should","be","used","when","the","same","training","data","is","used","for","all","outputs",".","Outputs","are","modeled","independently","by","using","a","different","batch","for","each","output",".",":","meta","private",":"]
docstr: Transforms tensor arguments: for single output models, the output
  dimension is squeezed and for multi-output models, the output dimension is
  transformed into the left-most batch dimension.
  
  Args:
      X: A `n x d` or `batch_shape x n x d` (batch mode) tensor of training
          features.
      Y: A `n x m` or `batch_shape x n x m` (batch mode) tensor of
          training observations.
      Yvar: A `n x m` or `batch_shape x n x m` (batch mode) tensor of
          observed measurement noise. Note: this will be None when using a model
          that infers the noise level (e.g. a `SingleTaskGP`).
  
  Returns:
      3-element tuple containing
  
      - A `input_batch_shape x (m) x n x d` tensor of training features.
      - A `target_batch_shape x (m) x n` tensor of training observations.
      - A `target_batch_shape x (m) x n` tensor observed measurement noise
          (or None).
docstr_tok: ["Transforms","tensor","arguments",":","for","single","output","models",",","the","output","dimension","is","squeezed","and","for","multi-output","models",",","the","output","dimension","is","transformed","into","the","left-most","batch","dimension",".","Args",":","X",":","A","`","n","x","d","`","or","`","batch_shape","x","n","x","d","`","(","batch","mode",")","tensor","of","training","features",".","Y",":","A","`","n","x","m","`","or","`","batch_shape","x","n","x","m","`","(","batch","mode",")","tensor","of","training","observations",".","Yvar",":","A","`","n","x","m","`","or","`","batch_shape","x","n","x","m","`","(","batch","mode",")","tensor","of","observed","measurement","noise",".","Note",":","this","will","be","None","when","using","a","model","that","infers","the","noise","level","(","e.g",".","a","`","SingleTaskGP","`",")",".","Returns",":","3-element","tuple","containing","-","A","`","input_batch_shape","x","(","m",")","x","n","x","d","`","tensor","of","training","features",".","-","A","`","target_batch_shape","x","(","m",")","x","n","`","tensor","of","training","observations",".","-","A","`","target_batch_shape","x","(","m",")","x","n","`","tensor","observed","measurement","noise","(","or","None",")","."]
code: def _transform_tensor_args(
      self, X: Tensor, Y: Tensor, Yvar: Optional[Tensor] = None
  ) -> Tuple[Tensor, Tensor, Optional[Tensor]]:
      r"""Transforms tensor arguments: for single output models, the output
      dimension is squeezed and for multi-output models, the output dimension is
      transformed into the left-most batch dimension.
  
      Args:
          X: A `n x d` or `batch_shape x n x d` (batch mode) tensor of training
              features.
          Y: A `n x m` or `batch_shape x n x m` (batch mode) tensor of
              training observations.
          Yvar: A `n x m` or `batch_shape x n x m` (batch mode) tensor of
              observed measurement noise. Note: this will be None when using a model
              that infers the noise level (e.g. a `SingleTaskGP`).
  
      Returns:
          3-element tuple containing
  
          - A `input_batch_shape x (m) x n x d` tensor of training features.
          - A `target_batch_shape x (m) x n` tensor of training observations.
          - A `target_batch_shape x (m) x n` tensor observed measurement noise
              (or None).
      """
      if self._num_outputs > 1:
          return multioutput_to_batch_mode_transform(
              train_X=X,
              train_Y=Y,
              train_Yvar=Yvar,
              num_outputs=self._num_outputs,
          )
      return (
          X,
          Y.squeeze(-1),
          None if Yvar is None else Yvar.squeeze(-1),
      )
  
imports: from __future__ import annotations
  import itertools
  import warnings
  from abc import ABC
  from copy import deepcopy
  from typing import Any, List, Optional, Tuple, TYPE_CHECKING, Union
  import torch
  from botorch.acquisition.objective import PosteriorTransform
  from botorch.exceptions.errors import BotorchTensorDimensionError, InputDataError
  from botorch.exceptions.warnings import _get_single_precision_warning, BotorchTensorDimensionWarning
  from botorch.models.model import Model, ModelList
  from botorch.models.utils import _make_X_full, add_output_dim, gpt_posterior_settings, mod_batch_shape, multioutput_to_batch_mode_transform
  from botorch.posteriors.fully_bayesian import GaussianMixturePosterior
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.utils.multitask import separate_mtmvn
  from botorch.utils.transforms import is_ensemble
  from gpytorch.distributions import MultitaskMultivariateNormal, MultivariateNormal
  from gpytorch.likelihoods.gaussian_likelihood import FixedNoiseGaussianLikelihood
  from linear_operator.operators import BlockDiagLinearOperator, CatLinearOperator
  from torch import Tensor
label_desc: Use image node_id 4 for calling the BatchedMultiOutputGPyTorchModel obj's underlying member method code with example usage: obj._transform_tensor_args(X, Y, Yvar) and returns: X,  Y,  unknown, multioutput_to_batch_mode_transform