class_docstr: A convenient extension of the :class:`~gpytorch.likelihoods.GaussianLikelihood` to the multitask setting that allows
  for a full cross-task covariance structure for the noise. The fitted covariance matrix has rank `rank`.
  If a strictly diagonal task noise covariance matrix is desired, then rank=0 should be set. (This option still
  allows for a different `noise` parameter for each task.)
  
  Like the Gaussian likelihood, this object can be used with exact inference.
  
  .. note::
      At least one of :attr:`has_global_noise` or :attr:`has_task_noise` should be specified.
  
  .. note::
      MultittaskGaussianLikelihood has an analytic marginal distribution.
  
  :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_prior: Prior to use over the task noise correlation
      matrix. Only used when :math:`\text{rank} > 0`.
  :param batch_shape: Number of batches.
  :param has_global_noise: Whether to include a :math:`\sigma^2 \mathbf I_{nt}` term in the noise model.
  :param has_task_noise: Whether to include task-specific noise terms, which add
      :math:`\mathbf I_n \otimes \mathbf D_T` into the noise model.
  
  :ivar torch.Tensor task_noise_covar: The inter-task noise covariance matrix
  :ivar torch.Tensor task_noises: (Optional) task specific noise variances (added onto the `task_noise_covar`)
  :ivar torch.Tensor noise: (Optional) global noise variance (added onto the `task_noise_covar`)
class_docstr_tok: ["A","convenient","extension","of","the",":","class",":","`","~gpytorch.likelihoods.GaussianLikelihood","`","to","the","multitask","setting","that","allows","for","a","full","cross-task","covariance","structure","for","the","noise",".","The","fitted","covariance","matrix","has","rank","`","rank","`",".","If","a","strictly","diagonal","task","noise","covariance","matrix","is","desired",",","then","rank=0","should","be","set",".","(","This","option","still","allows","for","a","different","`","noise","`","parameter","for","each","task",".",")","Like","the","Gaussian","likelihood",",","this","object","can","be","used","with","exact","inference",".","..","note",":",":","At","least","one","of",":","attr",":","`","has_global_noise","`","or",":","attr",":","`","has_task_noise","`","should","be","specified",".","..","note",":",":","MultittaskGaussianLikelihood","has","an","analytic","marginal","distribution",".",":","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_prior",":","Prior","to","use","over","the","task","noise","correlation","matrix",".","Only","used","when",":","math",":","`","\\text","{","rank","}",">","0","`",".",":","param","batch_shape",":","Number","of","batches",".",":","param","has_global_noise",":","Whether","to","include","a",":","math",":","`","\\sigma^2","\\mathbf","I_","{","nt","}","`","term","in","the","noise","model",".",":","param","has_task_noise",":","Whether","to","include","task-specific","noise","terms",",","which","add",":","math",":","`","\\mathbf","I_n","\\otimes","\\mathbf","D_T","`","into","the","noise","model",".",":","ivar","torch.Tensor","task_noise_covar",":","The","inter-task","noise","covariance","matrix",":","ivar","torch.Tensor","task_noises",":","(","Optional",")","task","specific","noise","variances","(","added","onto","the","`","task_noise_covar","`",")",":","ivar","torch.Tensor","noise",":","(","Optional",")","global","noise","variance","(","added","onto","the","`","task_noise_covar","`",")"]
code: def __init__(
      self,
      num_tasks: int,
      rank: int = 0,
      batch_shape: torch.Size = torch.Size(),
      task_prior: Optional[Prior] = None,
      noise_prior: Optional[Prior] = None,
      noise_constraint: Optional[Interval] = None,
      has_global_noise: bool = True,
      has_task_noise: bool = True,
  ) -> None:
      super(Likelihood, self).__init__()  # pyre-ignore[20]
      if noise_constraint is None:
          noise_constraint = GreaterThan(1e-4)
  
      if not has_task_noise and not has_global_noise:
          raise ValueError(
              "At least one of has_task_noise or has_global_noise must be specified. "
              "Attempting to specify a likelihood that has no noise terms."
          )
  
      if has_task_noise:
          if rank == 0:
              self.register_parameter(
                  name="raw_task_noises",
                  parameter=torch.nn.Parameter(
                      torch.zeros(*batch_shape, num_tasks)
                  ),
              )
              self.register_constraint(
                  "raw_task_noises", noise_constraint
              )
              if noise_prior is not None:
                  self.register_prior(
                      "raw_task_noises_prior",
                      noise_prior,
                      lambda m: m.task_noises,
                  )
              if task_prior is not None:
                  raise RuntimeError(
                      "Cannot set a `task_prior` if rank=0"
                  )
          else:
              self.register_parameter(
                  name="task_noise_covar_factor",
                  parameter=torch.nn.Parameter(
                      torch.randn(*batch_shape, num_tasks, rank)
                  ),
              )
              if task_prior is not None:
                  self.register_prior(
                      "MultitaskErrorCovariancePrior",
                      task_prior,
                      lambda m: m._eval_covar_matrix,
                  )
      self.num_tasks = num_tasks
      self.rank = rank
  
      if has_global_noise:
          self.register_parameter(
              name="raw_noise",
              parameter=torch.nn.Parameter(
                  torch.zeros(*batch_shape, 1)
              ),
          )
          self.register_constraint("raw_noise", noise_constraint)
          if noise_prior is not None:
              self.register_prior(
                  "raw_noise_prior", noise_prior, lambda m: m.noise
              )
  
      self.has_global_noise = has_global_noise
      self.has_task_noise = has_task_noise
  
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 1 to create a new MultitaskGaussianLikelihood object from inherited base classes: _MultitaskGaussianLikelihoodBase with example: obj = MultitaskGaussianLikelihood(num_tasks, rank, batch_shape, task_prior, noise_prior, noise_constraint, has_global_noise, has_task_noise)