class_docstr: Hidden Markov Model with the joint distribution of initial state, hidden
  state, and observed state is a :class:`~pyro.distributions.MultivariateStudentT`
  distribution along the line of references [2] and [3]. This adapts [1]
  to parallelize over time to achieve O(log(time)) parallel complexity.
  
  This GammaGaussianHMM class corresponds to the generative model::
  
      s = Gamma(df/2, df/2).sample()
      z = scale(initial_dist, s).sample()
      x = []
      for t in range(num_events):
          z = z @ transition_matrix + scale(transition_dist, s).sample()
          x.append(z @ observation_matrix + scale(observation_dist, s).sample())
  
  where `scale(mvn(loc, precision), s) := mvn(loc, s * precision)`.
  
  The event_shape of this distribution includes time on the left::
  
      event_shape = (num_steps,) + observation_dist.event_shape
  
  This distribution supports any combination of homogeneous/heterogeneous
  time dependency of ``transition_dist`` and ``observation_dist``. However,
  because time is included in this distribution's event_shape, the
  homogeneous+homogeneous case will have a broadcastable event_shape with
  ``num_steps = 1``, allowing :meth:`log_prob` to work with arbitrary length
  data::
  
      event_shape = (1, obs_dim)  # homogeneous + homogeneous case
  
  **References:**
  
  [1] Simo Sarkka, Angel F. Garcia-Fernandez (2019)
      "Temporal Parallelization of Bayesian Filters and Smoothers"
      https://arxiv.org/pdf/1905.13002.pdf
  
  [2] F. J. Giron and J. C. Rojano (1994)
      "Bayesian Kalman filtering with elliptically contoured errors"
  
  [3] Filip Tronarp, Toni Karvonen, and Simo Sarkka (2019)
      "Student's t-filters for noise scale estimation"
      https://users.aalto.fi/~ssarkka/pub/SPL2019.pdf
  
  :ivar int hidden_dim: The dimension of the hidden state.
  :ivar int obs_dim: The dimension of the observed state.
  :param Gamma scale_dist: Prior of the mixing distribution.
  :param MultivariateNormal initial_dist: A distribution with unit scale mixing
      over initial states. This should have batch_shape broadcastable to
      ``self.batch_shape``.  This should have event_shape ``(hidden_dim,)``.
  :param ~torch.Tensor transition_matrix: A linear transformation of hidden
      state. This should have shape broadcastable to
      ``self.batch_shape + (num_steps, hidden_dim, hidden_dim)`` where the
      rightmost dims are ordered ``(old, new)``.
  :param MultivariateNormal transition_dist: A process noise distribution
      with unit scale mixing. This should have batch_shape broadcastable to
      ``self.batch_shape + (num_steps,)``. This should have event_shape
      ``(hidden_dim,)``.
  :param ~torch.Tensor observation_matrix: A linear transformation from hidden
      to observed state. This should have shape broadcastable to
      ``self.batch_shape + (num_steps, hidden_dim, obs_dim)``.
  :param MultivariateNormal observation_dist: An observation noise distribution
      with unit scale mixing. This should have batch_shape broadcastable to
      ``self.batch_shape + (num_steps,)``.
      This should have event_shape ``(obs_dim,)``.
  :param int duration: Optional size of the time axis ``event_shape[0]``.
      This is required when sampling from homogeneous HMMs whose parameters
      are not expanded along the time axis.
class_docstr_tok: ["Hidden","Markov","Model","with","the","joint","distribution","of","initial","state",",","hidden","state",",","and","observed","state","is","a",":","class",":","`","~pyro.distributions.MultivariateStudentT","`","distribution","along","the","line","of","references","[","2","]","and","[","3","]",".","This","adapts","[","1","]","to","parallelize","over","time","to","achieve","O","(","log","(","time",")",")","parallel","complexity",".","This","GammaGaussianHMM","class","corresponds","to","the","generative","model",":",":","s","=","Gamma","(","df\/2",",","df\/2",")",".sample","(",")","z","=","scale","(","initial_dist",",","s",")",".sample","(",")","x","=","[","]","for","t","in","range","(","num_events",")",":","z","=","z","@","transition_matrix","+","scale","(","transition_dist",",","s",")",".sample","(",")","x.append","(","z","@","observation_matrix","+","scale","(","observation_dist",",","s",")",".sample","(",")",")","where","`","scale","(","mvn","(","loc",",","precision",")",",","s",")",":","=","mvn","(","loc",",","s","*","precision",")","`",".","The","event_shape","of","this","distribution","includes","time","on","the","left",":",":","event_shape","=","(","num_steps",",",")","+","observation_dist.event_shape","This","distribution","supports","any","combination","of","homogeneous\/heterogeneous","time","dependency","of","``","transition_dist","``","and","``","observation_dist","``",".","However",",","because","time","is","included","in","this","distribution","'s","event_shape",",","the","homogeneous+homogeneous","case","will","have","a","broadcastable","event_shape","with","``","num_steps","=","1","``",",","allowing",":","meth",":","`","log_prob","`","to","work","with","arbitrary","length","data",":",":","event_shape","=","(","1",",","obs_dim",")","#","homogeneous","+","homogeneous","case","*","*","References",":","*","*","[","1","]","Simo","Sarkka",",","Angel","F.","Garcia-Fernandez","(","2019",")","``","Temporal","Parallelization","of","Bayesian","Filters","and","Smoothers","''","https",":","\/\/arxiv.org\/pdf\/1905.13002.pdf","[","2","]","F.","J.","Giron","and","J.","C.","Rojano","(","1994",")","``","Bayesian","Kalman","filtering","with","elliptically","contoured","errors","''","[","3","]","Filip","Tronarp",",","Toni","Karvonen",",","and","Simo","Sarkka","(","2019",")","``","Student","'s","t-filters","for","noise","scale","estimation","''","https",":","\/\/users.aalto.fi\/~ssarkka\/pub\/SPL2019.pdf",":","ivar","int","hidden_dim",":","The","dimension","of","the","hidden","state",".",":","ivar","int","obs_dim",":","The","dimension","of","the","observed","state",".",":","param","Gamma","scale_dist",":","Prior","of","the","mixing","distribution",".",":","param","MultivariateNormal","initial_dist",":","A","distribution","with","unit","scale","mixing","over","initial","states",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","``",".","This","should","have","event_shape","``","(","hidden_dim",",",")","``",".",":","param","~torch.Tensor","transition_matrix",":","A","linear","transformation","of","hidden","state",".","This","should","have","shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",","hidden_dim",",","hidden_dim",")","``","where","the","rightmost","dims","are","ordered","``","(","old",",","new",")","``",".",":","param","MultivariateNormal","transition_dist",":","A","process","noise","distribution","with","unit","scale","mixing",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","hidden_dim",",",")","``",".",":","param","~torch.Tensor","observation_matrix",":","A","linear","transformation","from","hidden","to","observed","state",".","This","should","have","shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",","hidden_dim",",","obs_dim",")","``",".",":","param","MultivariateNormal","observation_dist",":","An","observation","noise","distribution","with","unit","scale","mixing",".","This","should","have","batch_shape","broadcastable","to","``","self.batch_shape","+","(","num_steps",",",")","``",".","This","should","have","event_shape","``","(","obs_dim",",",")","``",".",":","param","int","duration",":","Optional","size","of","the","time","axis","``","event_shape","[","0","]","``",".","This","is","required","when","sampling","from","homogeneous","HMMs","whose","parameters","are","not","expanded","along","the","time","axis","."]
code: def expand(self, batch_shape, _instance=None):
      new = self._get_checked_instance(GammaGaussianHMM, _instance)
      batch_shape = torch.Size(
          broadcast_shape(self.batch_shape, batch_shape)
      )
      new.hidden_dim = self.hidden_dim
      new.obs_dim = self.obs_dim
      # We only need to expand one of the inputs, since batch_shape is determined
      # by broadcasting all three. To save computation in sequential_gaussian_tensordot(),
      # we expand only _init, which is applied only after sequential_gaussian_tensordot().
      new._init = self._init.expand(batch_shape)
      new._trans = self._trans
      new._obs = self._obs
      super(GammaGaussianHMM, new).__init__(
          self.duration,
          batch_shape,
          self.event_shape,
          validate_args=False,
      )
      new._validate_args = self.__dict__.get("_validate_args")
      return new
  
imports: import torch
  import torch.nn.functional
  from pyro.ops.gamma_gaussian import GammaGaussian, gamma_and_mvn_to_gamma_gaussian, gamma_gaussian_tensordot, matrix_and_mvn_to_gamma_gaussian
  from pyro.ops.gaussian import Gaussian, gaussian_tensordot, matrix_and_mvn_to_gaussian, mvn_to_gaussian, sequential_gaussian_filter_sample, sequential_gaussian_tensordot
  from pyro.ops.indexing import Vindex
  from pyro.ops.special import safe_log
  from pyro.ops.tensor_utils import cholesky_solve, safe_cholesky
  from .None import constraints
  from .torch import Categorical, Gamma, Independent, MultivariateNormal
  from .torch_distribution import TorchDistribution
  from .util import broadcast_shape, torch_jit_script_if_tracing
label_desc: Use image node_id 2 for calling the GammaGaussianHMM obj's underlying member method code with example usage: obj.expand(batch_shape, _instance) and returns: new