class_docstr: Base class for multi-task Gaussian Likelihoods, supporting general heteroskedastic noise models.
  
  :param num_tasks: Number of tasks.
  :param noise_covar: A model for the noise covariance. This can be a simple homoskedastic noise model, or a GP
      that is to be fitted on the observed measurement errors.
  :param rank: The rank of the task noise covariance matrix to fit. If `rank`
      is set to 0, then a diagonal covariance matrix is fit.
  :param task_correlation_prior: Prior to use over the task noise correlation
      matrix. Only used when :math:`\text{rank} > 0`.
  :param batch_shape: Number of batches.
class_docstr_tok: ["Base","class","for","multi-task","Gaussian","Likelihoods",",","supporting","general","heteroskedastic","noise","models",".",":","param","num_tasks",":","Number","of","tasks",".",":","param","noise_covar",":","A","model","for","the","noise","covariance",".","This","can","be","a","simple","homoskedastic","noise","model",",","or","a","GP","that","is","to","be","fitted","on","the","observed","measurement","errors",".",":","param","rank",":","The","rank","of","the","task","noise","covariance","matrix","to","fit",".","If","`","rank","`","is","set","to","0",",","then","a","diagonal","covariance","matrix","is","fit",".",":","param","task_correlation_prior",":","Prior","to","use","over","the","task","noise","correlation","matrix",".","Only","used","when",":","math",":","`","\\text","{","rank","}",">","0","`",".",":","param","batch_shape",":","Number","of","batches","."]
docstr: If :math:`\text{rank} = 0`, adds the task noises to the diagonal of the
  covariance matrix of the supplied
  :obj:`~gpytorch.distributions.MultivariateNormal` or
  :obj:`~gpytorch.distributions.MultitaskMultivariateNormal`.  Otherwise,
  adds a rank `rank` covariance matrix to it.
  
  To accomplish this, we form a new
  :obj:`~linear_operator.operators.KroneckerProductLinearOperator`
  between :math:`I_{n}`, an identity matrix with size equal to the data
  and a (not necessarily diagonal) matrix containing the task noises
  :math:`D_{t}`.
  
  We also incorporate a shared `noise` parameter from the base
  :class:`gpytorch.likelihoods.GaussianLikelihood` that we extend.
  
  The final covariance matrix after this method is then
  :math:`\mathbf K + \mathbf D_{t} \otimes \mathbf I_{n} + \sigma^{2} \mathbf I_{nt}`.
  
  :param function_dist: Random variable whose covariance
      matrix is a :obj:`~linear_operator.operators.LinearOperator` we intend to augment.
  :rtype: `gpytorch.distributions.MultitaskMultivariateNormal`:
  :return: A new random variable whose covariance matrix is a
      :obj:`~linear_operator.operators.LinearOperator` with
      :math:`\mathbf D_{t} \otimes \mathbf I_{n}` and :math:`\sigma^{2} \mathbf I_{nt}` added.
docstr_tok: ["If",":","math",":","`","\\text","{","rank","}","=","0","`",",","adds","the","task","noises","to","the","diagonal","of","the","covariance","matrix","of","the","supplied",":","obj",":","`","~gpytorch.distributions.MultivariateNormal","`","or",":","obj",":","`","~gpytorch.distributions.MultitaskMultivariateNormal","`",".","Otherwise",",","adds","a","rank","`","rank","`","covariance","matrix","to","it",".","To","accomplish","this",",","we","form","a","new",":","obj",":","`","~linear_operator.operators.KroneckerProductLinearOperator","`","between",":","math",":","`","I_","{","n","}","`",",","an","identity","matrix","with","size","equal","to","the","data","and","a","(","not","necessarily","diagonal",")","matrix","containing","the","task","noises",":","math",":","`","D_","{","t","}","`",".","We","also","incorporate","a","shared","`","noise","`","parameter","from","the","base",":","class",":","`","gpytorch.likelihoods.GaussianLikelihood","`","that","we","extend",".","The","final","covariance","matrix","after","this","method","is","then",":","math",":","`","\\mathbf","K","+","\\mathbf","D_","{","t","}","\\otimes","\\mathbf","I_","{","n","}","+","\\sigma^","{","2","}","\\mathbf","I_","{","nt","}","`",".",":","param","function_dist",":","Random","variable","whose","covariance","matrix","is","a",":","obj",":","`","~linear_operator.operators.LinearOperator","`","we","intend","to","augment",".",":","rtype",":","`","gpytorch.distributions.MultitaskMultivariateNormal","`",":",":","return",":","A","new","random","variable","whose","covariance","matrix","is","a",":","obj",":","`","~linear_operator.operators.LinearOperator","`","with",":","math",":","`","\\mathbf","D_","{","t","}","\\otimes","\\mathbf","I_","{","n","}","`","and",":","math",":","`","\\sigma^","{","2","}","\\mathbf","I_","{","nt","}","`","added","."]
code: def marginal(
      self,
      function_dist: MultitaskMultivariateNormal,
      *params: Any,
      **kwargs: Any,
  ) -> MultitaskMultivariateNormal:  # pyre-ignore[14]
      r"""
      If :math:`\text{rank} = 0`, adds the task noises to the diagonal of the
      covariance matrix of the supplied
      :obj:`~gpytorch.distributions.MultivariateNormal` or
      :obj:`~gpytorch.distributions.MultitaskMultivariateNormal`.  Otherwise,
      adds a rank `rank` covariance matrix to it.
  
      To accomplish this, we form a new
      :obj:`~linear_operator.operators.KroneckerProductLinearOperator`
      between :math:`I_{n}`, an identity matrix with size equal to the data
      and a (not necessarily diagonal) matrix containing the task noises
      :math:`D_{t}`.
  
      We also incorporate a shared `noise` parameter from the base
      :class:`gpytorch.likelihoods.GaussianLikelihood` that we extend.
  
      The final covariance matrix after this method is then
      :math:`\mathbf K + \mathbf D_{t} \otimes \mathbf I_{n} + \sigma^{2} \mathbf I_{nt}`.
  
      :param function_dist: Random variable whose covariance
          matrix is a :obj:`~linear_operator.operators.LinearOperator` we intend to augment.
      :rtype: `gpytorch.distributions.MultitaskMultivariateNormal`:
      :return: A new random variable whose covariance matrix is a
          :obj:`~linear_operator.operators.LinearOperator` with
          :math:`\mathbf D_{t} \otimes \mathbf I_{n}` and :math:`\sigma^{2} \mathbf I_{nt}` added.
      """
      mean, covar = (
          function_dist.mean,
          function_dist.lazy_covariance_matrix,
      )
  
      # ensure that sumKroneckerLT is actually called
      if isinstance(covar, LazyEvaluatedKernelTensor):
          covar = covar.evaluate_kernel()
  
      covar_kron_lt = self._shaped_noise_covar(
          mean.shape,
          add_noise=self.has_global_noise,
          interleaved=function_dist._interleaved,
      )
      covar = covar + covar_kron_lt
  
      return function_dist.__class__(
          mean, covar, interleaved=function_dist._interleaved
      )
  
imports: from typing import Any, Optional, Union
  import torch
  from linear_operator import to_linear_operator
  from linear_operator.operators import ConstantDiagLinearOperator, DiagLinearOperator, KroneckerProductDiagLinearOperator, KroneckerProductLinearOperator, LinearOperator, RootLinearOperator
  from torch import Tensor
  from torch.distributions import Normal
  from ..constraints import GreaterThan, Interval
  from ..distributions import base_distributions, MultitaskMultivariateNormal
  from ..lazy import LazyEvaluatedKernelTensor
  from ..likelihoods import _GaussianLikelihoodBase, Likelihood
  from ..priors import Prior
  from .noise_models import FixedGaussianNoise, Noise
label_desc: Use image node_id 3 for calling the _MultitaskGaussianLikelihoodBase obj's underlying member method code with example usage: obj.marginal(function_dist) and returns: function_dist