docstr: Computes three types of Sobol indices:
  first order indices, total indices and second order indices (if specified ).
  
  Args:
      model: Botorch model
      bounds: `2 x d` parameter bounds over which to evaluate model sensitivity.
      method: if "predictive mean", the predictive mean is used for indices
          computation. If "GP samples", posterior sampling is used instead.
      num_mc_samples: The number of montecarlo grid samples
      second_order: If True, the second order indices are computed.
      input_qmc: If True, a qmc Sobol grid is use instead of uniformly random.
      num_bootstrap_samples: If bootstrap is true, the number of bootstraps has
          to be specified.
      mini_batch_size: The size of the mini-batches used while evaluating the
          model posterior. Increasing this will increase the memory usage.
docstr_tok: ["Computes","three","types","of","Sobol","indices",":","first","order","indices",",","total","indices","and","second","order","indices","(","if","specified",")",".","Args",":","model",":","Botorch","model","bounds",":","`","2","x","d","`","parameter","bounds","over","which","to","evaluate","model","sensitivity",".","method",":","if","``","predictive","mean","''",",","the","predictive","mean","is","used","for","indices","computation",".","If","``","GP","samples","''",",","posterior","sampling","is","used","instead",".","num_mc_samples",":","The","number","of","montecarlo","grid","samples","second_order",":","If","True",",","the","second","order","indices","are","computed",".","input_qmc",":","If","True",",","a","qmc","Sobol","grid","is","use","instead","of","uniformly","random",".","num_bootstrap_samples",":","If","bootstrap","is","true",",","the","number","of","bootstraps","has","to","be","specified",".","mini_batch_size",":","The","size","of","the","mini-batches","used","while","evaluating","the","model","posterior",".","Increasing","this","will","increase","the","memory","usage","."]
code: def __init__(
      self,
      model: Model,  # TODO: narrow type down. E.g. ModelListGP does not work.
      bounds: torch.Tensor,
      num_mc_samples: int = 10**4,
      second_order: bool = False,
      input_qmc: bool = False,
      num_bootstrap_samples: int = 1,
      link_function: Callable[
          [torch.Tensor, torch.Tensor], torch.Tensor
      ] = GaussianLinkMean,
      mini_batch_size: int = 128,
  ) -> None:
      r"""Computes three types of Sobol indices:
      first order indices, total indices and second order indices (if specified ).
  
      Args:
          model: Botorch model
          bounds: `2 x d` parameter bounds over which to evaluate model sensitivity.
          method: if "predictive mean", the predictive mean is used for indices
              computation. If "GP samples", posterior sampling is used instead.
          num_mc_samples: The number of montecarlo grid samples
          second_order: If True, the second order indices are computed.
          input_qmc: If True, a qmc Sobol grid is use instead of uniformly random.
          num_bootstrap_samples: If bootstrap is true, the number of bootstraps has
              to be specified.
          mini_batch_size: The size of the mini-batches used while evaluating the
              model posterior. Increasing this will increase the memory usage.
      """
      self.model = model
      self.second_order = second_order
      self.input_qmc = input_qmc
      # pyre-fixme[4]: Attribute must be annotated.
      self.bootstrap = num_bootstrap_samples > 1
      self.num_bootstrap_samples = num_bootstrap_samples
      self.num_mc_samples = num_mc_samples
  
      def input_function(x: Tensor) -> Tensor:
          with torch.no_grad():
              means, variances = [], []
              # Since we're only looking at mean & variance, we can freely
              # use mini-batches.
              for x_split in x.split(split_size=mini_batch_size):
                  p = checked_cast(
                      GPyTorchPosterior, self.model.posterior(x_split)
                  )
                  means.append(p.mean)
                  variances.append(p.variance)
          return link_function(torch.cat(means), torch.cat(variances))
  
      self.sensitivity = SobolSensitivity(
          bounds=bounds,
          num_mc_samples=self.num_mc_samples,
          input_function=input_function,
          second_order=self.second_order,
          input_qmc=self.input_qmc,
          num_bootstrap_samples=self.num_bootstrap_samples,
      )
      self.sensitivity.evalute_function()
  
imports: from copy import deepcopy
  from typing import Any, Callable, Dict, List, Optional, Union
  import numpy
  import torch
  from ax.modelbridge.torch import TorchModelBridge
  from ax.models.torch.botorch import BotorchModel
  from ax.models.torch.botorch_modular.model import BoTorchModel
  from ax.utils.common.typeutils import checked_cast
  from botorch.models.model import Model, ModelList
  from botorch.posteriors.gpytorch import GPyTorchPosterior
  from botorch.sampling.normal import SobolQMCNormalSampler
  from botorch.utils.sampling import draw_sobol_samples
  from botorch.utils.transforms import unnormalize
  from torch import Tensor
label_desc: Use image node_id 1 to create a new SobolSensitivityGPMean object from inherited base classes: object with example: obj = SobolSensitivityGPMean(model, bounds, num_mc_samples, second_order, input_qmc, num_bootstrap_samples, link_function, mini_batch_size)