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","."]
code: def __init__(
      self,
      num_tasks: int,
      noise_covar: Union[Noise, FixedGaussianNoise],
      rank: int = 0,
      task_correlation_prior: Optional[Prior] = None,
      batch_shape: torch.Size = torch.Size(),
  ) -> None:
      super().__init__(noise_covar=noise_covar)
      if rank != 0:
          if rank > num_tasks:
              raise ValueError(
                  f"Cannot have rank ({rank}) greater than num_tasks ({num_tasks})"
              )
          tidcs = torch.tril_indices(num_tasks, rank, dtype=torch.long)
          self.tidcs: Tensor = tidcs[
              :, 1:
          ]  # (1, 1) must be 1.0, no need to parameterize this
          task_noise_corr = torch.randn(
              *batch_shape, self.tidcs.size(-1)
          )
          self.register_parameter(
              "task_noise_corr", torch.nn.Parameter(task_noise_corr)
          )
          if task_correlation_prior is not None:
              self.register_prior(
                  "MultitaskErrorCorrelationPrior",
                  task_correlation_prior,
                  lambda m: m._eval_corr_matrix,
              )
      elif task_correlation_prior is not None:
          raise ValueError(
              "Can only specify task_correlation_prior if rank>0"
          )
      self.num_tasks = num_tasks
      self.rank = rank
  
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 _MultitaskGaussianLikelihoodBase object from inherited base classes: _GaussianLikelihoodBase with example: obj = _MultitaskGaussianLikelihoodBase(num_tasks, noise_covar, rank, task_correlation_prior, batch_shape)