class_docstr: Represents a layer in a deep GP where inference is performed via the doubly stochastic method of
  Salimbeni et al., 2017. Upon calling, instead of returning a variational distribution q(f), returns samples
  from the variational distribution.
  
  See the documentation for __call__ below for more details below. Note that the behavior of __call__
  will change to be much more elegant with multiple batch dimensions; however, the interface doesn't really
  change.
  
  :param ~gpytorch.variational.VariationalStrategy variational_strategy: Strategy for
      changing q(u) -> q(f) (see other VI docs)
  :param int input_dims`: Dimensionality of input data expected by each GP
  :param int output_dims: (default None) Number of GPs in this layer, equivalent to
      output dimensionality. If set to `None`, then the output dimension will be squashed.
  
  Forward data through this hidden GP layer. The output is a MultitaskMultivariateNormal distribution
  (or MultivariateNormal distribution is output_dims=None).
  
  If the input is >=2 dimensional Tensor (e.g. `n x d`), we pass the input through each hidden GP,
  resulting in a `n x h` multitask Gaussian distribution (where all of the `h` tasks represent an
  output dimension and are independent from one another).  We then draw `s` samples from these Gaussians,
  resulting in a `s x n x h` MultitaskMultivariateNormal distribution.
  
  If the input is a >=3 dimensional Tensor, and the `are_samples=True` kwarg is set, then we assume that
  the outermost batch dimension is a samples dimension. The output will have the same number of samples.
  For example, a `s x b x n x d` input will result in a `s x b x n x h` MultitaskMultivariateNormal distribution.
  
  The goal of these last two points is that if you have a tensor `x` that is `n x d`, then
  
      >>> hidden_gp2(hidden_gp(x))
  
  will just work, and return a tensor of size `s x n x h2`, where `h2` is the output dimensionality of
  hidden_gp2. In this way, hidden GP layers are easily composable.
class_docstr_tok: ["Represents","a","layer","in","a","deep","GP","where","inference","is","performed","via","the","doubly","stochastic","method","of","Salimbeni","et","al.",",","2017",".","Upon","calling",",","instead","of","returning","a","variational","distribution","q","(","f",")",",","returns","samples","from","the","variational","distribution",".","See","the","documentation","for","__call__","below","for","more","details","below",".","Note","that","the","behavior","of","__call__","will","change","to","be","much","more","elegant","with","multiple","batch","dimensions",";","however",",","the","interface","does","n't","really","change",".",":","param","~gpytorch.variational.VariationalStrategy","variational_strategy",":","Strategy","for","changing","q","(","u",")","-",">","q","(","f",")","(","see","other","VI","docs",")",":","param","int","input_dims","`",":","Dimensionality","of","input","data","expected","by","each","GP",":","param","int","output_dims",":","(","default","None",")","Number","of","GPs","in","this","layer",",","equivalent","to","output","dimensionality",".","If","set","to","`","None","`",",","then","the","output","dimension","will","be","squashed",".","Forward","data","through","this","hidden","GP","layer",".","The","output","is","a","MultitaskMultivariateNormal","distribution","(","or","MultivariateNormal","distribution","is","output_dims=None",")",".","If","the","input","is",">","=2","dimensional","Tensor","(","e.g",".","`","n","x","d","`",")",",","we","pass","the","input","through","each","hidden","GP",",","resulting","in","a","`","n","x","h","`","multitask","Gaussian","distribution","(","where","all","of","the","`","h","`","tasks","represent","an","output","dimension","and","are","independent","from","one","another",")",".","We","then","draw","`","s","`","samples","from","these","Gaussians",",","resulting","in","a","`","s","x","n","x","h","`","MultitaskMultivariateNormal","distribution",".","If","the","input","is","a",">","=3","dimensional","Tensor",",","and","the","`","are_samples=True","`","kwarg","is","set",",","then","we","assume","that","the","outermost","batch","dimension","is","a","samples","dimension",".","The","output","will","have","the","same","number","of","samples",".","For","example",",","a","`","s","x","b","x","n","x","d","`","input","will","result","in","a","`","s","x","b","x","n","x","h","`","MultitaskMultivariateNormal","distribution",".","The","goal","of","these","last","two","points","is","that","if","you","have","a","tensor","`","x","`","that","is","`","n","x","d","`",",","then",">",">",">","hidden_gp2","(","hidden_gp","(","x",")",")","will","just","work",",","and","return","a","tensor","of","size","`","s","x","n","x","h2","`",",","where","`","h2","`","is","the","output","dimensionality","of","hidden_gp2",".","In","this","way",",","hidden","GP","layers","are","easily","composable","."]
code: def __init__(self, variational_strategy, input_dims, output_dims):
      super(DeepGPLayer, self).__init__(variational_strategy)
      self.input_dims = input_dims
      self.output_dims = output_dims
  
imports: import warnings
  import torch
  from linear_operator.operators import BlockDiagLinearOperator
  from ...None import settings
  from ...distributions import MultitaskMultivariateNormal
  from ...likelihoods import Likelihood
  from ..approximate_gp import ApproximateGP
  from ..gp import GP
label_desc: Use image node_id 1 to create a new DeepGPLayer object from inherited base classes: ApproximateGP with example: obj = DeepGPLayer(variational_strategy, input_dims, output_dims)