class_docstr: A model for high-dimensional output regression.
  
  As described in [Zhe2019hogp]_. “Higher-order” means that the predictions
  are matrices (tensors) with at least two dimensions, such as images or
  grids of images, or measurements taken from a region of at least two
  dimensions.
  The posterior uses Matheron's rule [Doucet2010sampl]_
  as described in [Maddox2021bohdo]_.
  
  `HigherOrderGP` differs from a "vector” multi-output model in that it uses
  Kronecker algebra to obtain parsimonious covariance matrices for these
  outputs (see `KroneckerMultiTaskGP` for more information). For example,
  imagine a 10 x 20 x 30 grid of images. If we were to vectorize the
  resulting 6,000 data points in order to use them in a non-higher-order GP,
  they would have a 6,000 x 6,000 covariance matrix, with 36 million entries.
  The Kronecker structure allows representing this as a product of 10x10,
  20x20, and 30x30 covariance matrices, with only 1,400 entries.
  
  NOTE: This model requires the use of specialized Kronecker solves in
  linear operator, which are disabled by default in BoTorch. These are enabled
  by default in the `HigherOrderGP.posterior` call. However, they need to be
  manually enabled by the user during model fitting.
  
  Example:
      >>> from linear_operator.settings import _fast_solves
      >>> model = SingleTaskGP(train_X, train_Y)
      >>> mll = ExactMarginalLogLikelihood(model.likelihood, model)
      >>> with _fast_solves(True):
      >>>     fit_gpytorch_mll_torch(mll)
      >>> samples = model.posterior(test_X).rsample()
code: def forward(self, X: Tensor) -> MultivariateNormal:
      if self.training:
          X = self.transform_inputs(X)
  
      covariance_list = []
      covariance_list.append(self.covar_modules[0](X))
  
      for cm, param in zip(
          self.covar_modules[1:], self.latent_parameters
      ):
          if not self.training:
              with torch.no_grad():
                  covariance_list.append(cm(param))
          else:
              covariance_list.append(cm(param))
  
      # check batch_shapes
      if (
          covariance_list[0].batch_shape
          != covariance_list[1].batch_shape
      ):
          for i in range(1, len(covariance_list)):
              cm = covariance_list[i]
              covariance_list[i] = BatchRepeatLinearOperator(
                  cm, covariance_list[0].batch_shape
              )
      kronecker_covariance = KroneckerProductLinearOperator(
          *covariance_list
      )
  
      # TODO: expand options for the mean module via batch shaping?
      mean = torch.zeros(
          *covariance_list[0].batch_shape,
          kronecker_covariance.shape[-1],
          device=kronecker_covariance.device,
          dtype=kronecker_covariance.dtype,
      )
      return MultivariateNormal(mean, kronecker_covariance)
  
imports: from __future__ import annotations
  import warnings
  from contextlib import ExitStack
  from typing import Any, List, Optional, Tuple, Union
  import torch
  from botorch.acquisition.objective import PosteriorTransform
  from botorch.models.gpytorch import BatchedMultiOutputGPyTorchModel
  from botorch.models.model import FantasizeMixin
  from botorch.models.transforms.input import InputTransform
  from botorch.models.transforms.outcome import OutcomeTransform, Standardize
  from botorch.models.utils import gpt_posterior_settings
  from botorch.models.utils.gpytorch_modules import get_gaussian_likelihood_with_gamma_prior
  from botorch.posteriors import GPyTorchPosterior, HigherOrderGPPosterior, TransformedPosterior
  from gpytorch.distributions import MultivariateNormal
  from gpytorch.kernels import Kernel, MaternKernel
  from gpytorch.likelihoods import Likelihood
  from gpytorch.models import ExactGP
  from gpytorch.priors.torch_priors import GammaPrior, MultivariateNormalPrior
  from gpytorch.settings import fast_pred_var, skip_posterior_variances
  from linear_operator.operators import BatchRepeatLinearOperator, DiagLinearOperator, KroneckerProductLinearOperator, LinearOperator, ZeroLinearOperator
  from linear_operator.settings import _fast_solves
  from torch import Tensor
  from torch.nn import ModuleList, Parameter, ParameterList
label_desc: Use image node_id 3 for calling the HigherOrderGP obj's underlying member method code with example usage: obj.forward(X) and returns: MultivariateNormal