docstr: Draw forward samples from the model. At each step, we sample an inter-
  event time and feed it into the RNN to obtain the parameters for the
  next distribution over the inter-event time.
  
  Parameters
  ----------
  F
      MXNet backend.
  past_target
      Tensor with past observations.
      Shape: (batch_size, context_length, target_dim). Has to comply
      with :code:`self.context_interval_length`.
  past_valid_length
      The `valid_length` or number of valid entries in the past_target
      Tensor. Shape: (batch_size,)
  
  Returns
  -------
  sampled_target: Tensor
      Predicted inter-event times and marks.
      Shape: (samples, batch_size, max_prediction_length, target_dim).
  sampled_valid_length: Tensor
      The number of valid entries in the time axis of each sample.
      Shape (samples, batch_size)
docstr_tok: ["Draw","forward","samples","from","the","model",".","At","each","step",",","we","sample","an","inter-","event","time","and","feed","it","into","the","RNN","to","obtain","the","parameters","for","the","next","distribution","over","the","inter-event","time",".","Parameters","--","--","--","--","--","F","MXNet","backend",".","past_target","Tensor","with","past","observations",".","Shape",":","(","batch_size",",","context_length",",","target_dim",")",".","Has","to","comply","with",":","code",":","`","self.context_interval_length","`",".","past_valid_length","The","`","valid_length","`","or","number","of","valid","entries","in","the","past_target","Tensor",".","Shape",":","(","batch_size",",",")","Returns","--","--","--","-","sampled_target",":","Tensor","Predicted","inter-event","times","and","marks",".","Shape",":","(","samples",",","batch_size",",","max_prediction_length",",","target_dim",")",".","sampled_valid_length",":","Tensor","The","number","of","valid","entries","in","the","time","axis","of","each","sample",".","Shape","(","samples",",","batch_size",")"]
code: def hybrid_forward(
      self,
      F,
      past_target: Tensor,
      past_valid_length: Tensor,
  ) -> Tuple[Tensor, Tensor]:
      """
      Draw forward samples from the model. At each step, we sample an inter-
      event time and feed it into the RNN to obtain the parameters for the
      next distribution over the inter-event time.
  
      Parameters
      ----------
      F
          MXNet backend.
      past_target
          Tensor with past observations.
          Shape: (batch_size, context_length, target_dim). Has to comply
          with :code:`self.context_interval_length`.
      past_valid_length
          The `valid_length` or number of valid entries in the past_target
          Tensor. Shape: (batch_size,)
  
      Returns
      -------
      sampled_target: Tensor
          Predicted inter-event times and marks.
          Shape: (samples, batch_size, max_prediction_length, target_dim).
      sampled_valid_length: Tensor
          The number of valid entries in the time axis of each sample.
          Shape (samples, batch_size)
      """
      # Variable-length generation (while t < t_max) is a potential problem
      if F is mx.sym:
          raise ValueError(
              "The DeepTPP model currently doesn't support hybridization."
          )
  
      assert (
          past_target.shape[-1] == 2
      ), "TPP data should have two target_dim, interarrival times and marks"
  
      batch_size = past_target.shape[0]
  
      # condition the prediction network on the past events
      past_ia_times, past_marks = F.split(
          past_target, num_outputs=2, axis=-1
      )
      past_valid_length = past_valid_length.reshape(-1).astype(
          past_ia_times.dtype
      )
  
      if self.apply_log_to_rnn_inputs:
          past_ia_times_input = past_ia_times.clip(1e-8, np.inf).log()
      else:
          past_ia_times_input = past_ia_times
      rnn_input = F.concat(
          past_ia_times_input,
          self.embedding(past_marks.squeeze(axis=-1)),
          dim=-1,
      )
      rnn_output = self.rnn(rnn_input)  # (N, T, H)
      rnn_init_state = F.zeros([batch_size, 1, self.rnn_hidden_size])
  
      past_history_emb = F.concat(
          rnn_init_state, rnn_output, dim=1
      )  # (N, T + 1, H)
  
      # Select the history embedding after the last event in the past
      indices = F.stack(F.arange(batch_size), past_valid_length)
      history_emb = F.gather_nd(past_history_emb, indices)  # (N, H)
  
      num_total_samples = self.num_parallel_samples * batch_size
      history_emb = history_emb.expand_dims(0).repeat(
          self.num_parallel_samples, axis=0
      )  # (S, N, H)
      history_emb = history_emb.reshape(
          [num_total_samples, self.rnn_hidden_size]
      )  # (S * N, H)
  
      sampled_ia_times_list: List[nd.NDArray] = []
      sampled_marks_list: List[nd.NDArray] = []
      arrival_times = F.zeros([num_total_samples])
  
      # Time from the last observed event until the past interval end
      past_time_elapsed = past_ia_times.squeeze(axis=-1).sum(-1)
      past_time_remaining = (
          self.interval_length - past_time_elapsed
      )  # (N)
      past_time_remaining_repeat = (
          past_time_remaining.expand_dims(0)
          .repeat(self.num_parallel_samples, axis=0)
          .reshape([num_total_samples])
      )  # (S * N)
  
      first_step = True
      while F.sum(arrival_times < self.prediction_interval_length) > 0:
          # Sample the next inter-arrival time
          time_distr_args = self.time_distr_args_proj(history_emb)
          time_distr = self.time_distr_output.distribution(
              time_distr_args,
              scale=self.output_scale,
          )
          if first_step:
              # Time from the last event until the next event
              next_ia_times = time_distr.sample(
                  lower_bound=past_time_remaining_repeat
              )
              # Time from the prediction interval start until the next event
              clipped_ia_times = (
                  next_ia_times - past_time_remaining_repeat
              )
              sampled_ia_times_list.append(clipped_ia_times)
              arrival_times = arrival_times + clipped_ia_times
              first_step = False
          else:
              next_ia_times = time_distr.sample()
              sampled_ia_times_list.append(next_ia_times)
              arrival_times = arrival_times + next_ia_times
  
          # Sample the next marks
          if self.num_marks > 1:
              mark_distr_args = self.mark_distr_args_proj(history_emb)
              next_marks = self.mark_distr_output.distribution(
                  mark_distr_args
              ).sample()
          else:
              next_marks = F.zeros([num_total_samples])
  
          sampled_marks_list.append(next_marks)
  
          # Pass the generated ia_times & marks into the RNN to obtain
          # the next history embedding
          if self.apply_log_to_rnn_inputs:
              next_ia_times_input = next_ia_times.clip(
                  1e-8, np.inf
              ).log()
          else:
              next_ia_times_input = next_ia_times
          rnn_input = F.concat(
              next_ia_times_input.expand_dims(-1),
              self.embedding(next_marks),
              dim=-1,
          ).expand_dims(1)
  
          history_emb = self.rnn(rnn_input).squeeze(
              axis=1
          )  # (S * N, C)
  
      sampled_ia_times = F.stack(*sampled_ia_times_list, axis=-1)
      sampled_marks = F.stack(*sampled_marks_list, axis=-1).astype(
          "float32"
      )
  
      sampled_valid_length = F.sum(
          F.cumsum(sampled_ia_times, axis=1)
          < self.prediction_interval_length,
          axis=-1,
      )
  
      def _mask(x, sequence_length):
          return F.SequenceMask(
              data=x,
              sequence_length=sequence_length,
              axis=1,
              use_sequence_length=True,
          )
  
      sampled_ia_times = _mask(sampled_ia_times, sampled_valid_length)
      sampled_marks = _mask(sampled_marks, sampled_valid_length)
  
      sampled_ia_times = sampled_ia_times.reshape(
          [self.num_parallel_samples, batch_size, -1]
      )
      sampled_marks = sampled_marks.reshape(
          [self.num_parallel_samples, batch_size, -1]
      )
      sampled_valid_length = sampled_valid_length.reshape(
          [self.num_parallel_samples, batch_size]
      )
      sampled_target = F.stack(sampled_ia_times, sampled_marks, axis=-1)
      return sampled_target, sampled_valid_length
  
file_path: gluonts/src/gluonts/mx/model/tpp/deeptpp/_network.py
imports: from typing import List, Optional, Tuple
  import mxnet
  import numpy
  from mxnet import nd
  from gluonts.core.component import validated
  from gluonts.mx.model.tpp import distribution
  from gluonts.mx.model.tpp.distribution.base import TPPDistributionOutput
  from gluonts.mx import Tensor
  from gluonts.mx.distribution import CategoricalOutput
label_desc: Use image node_id 2 for calling the DeepTPPPredictionNetwork obj's underlying member method code with example usage: obj.hybrid_forward(F, past_target, past_valid_length) and returns: sampled_target,  sampled_valid_length, F