class_docstr: Implements multi-step prediction given a trained `DeepNPTSNetwork` model
  that outputs one-step-ahead forecast distribution.
class_docstr_tok: ["Implements","multi-step","prediction","given","a","trained","`","DeepNPTSNetwork","`","model","that","outputs","one-step-ahead","forecast","distribution","."]
docstr: Generates samples from the forecast distribution.
  
  Parameters
  ----------
  feat_static_cat
      Shape (-1, num_features).
  feat_static_real
      Shape (-1, num_features).
  past_target
      Shape (-1, context_length).
  past_observed_values
      Shape (-1, context_length).
  past_time_feat
      Shape (-1, context_length, self.num_time_features).
  future_time_feat
      Shape (-1, prediction_length, self.num_time_features).
  
  Returns
  -------
  torch.Tensor
      Tensor containing samples from the predicted distribution.
      Shape is (-1, self.num_parallel_samples, self.prediction_length).
docstr_tok: ["Generates","samples","from","the","forecast","distribution",".","Parameters","--","--","--","--","--","feat_static_cat","Shape","(","-1",",","num_features",")",".","feat_static_real","Shape","(","-1",",","num_features",")",".","past_target","Shape","(","-1",",","context_length",")",".","past_observed_values","Shape","(","-1",",","context_length",")",".","past_time_feat","Shape","(","-1",",","context_length",",","self.num_time_features",")",".","future_time_feat","Shape","(","-1",",","prediction_length",",","self.num_time_features",")",".","Returns","--","--","--","-","torch.Tensor","Tensor","containing","samples","from","the","predicted","distribution",".","Shape","is","(","-1",",","self.num_parallel_samples",",","self.prediction_length",")","."]
code: def forward(
      self,
      feat_static_cat: torch.Tensor,
      feat_static_real: torch.Tensor,
      past_target: torch.Tensor,
      past_observed_values: torch.Tensor,
      past_time_feat: torch.Tensor,
      future_time_feat: torch.Tensor,
  ):
      """Generates samples from the forecast distribution.
  
      Parameters
      ----------
      feat_static_cat
          Shape (-1, num_features).
      feat_static_real
          Shape (-1, num_features).
      past_target
          Shape (-1, context_length).
      past_observed_values
          Shape (-1, context_length).
      past_time_feat
          Shape (-1, context_length, self.num_time_features).
      future_time_feat
          Shape (-1, prediction_length, self.num_time_features).
  
      Returns
      -------
      torch.Tensor
          Tensor containing samples from the predicted distribution.
          Shape is (-1, self.num_parallel_samples, self.prediction_length).
      """
      # Blow up the initial `x` by the number of parallel samples required.
      # (batch_size * num_parallel_samples, context_length)
      past_target = past_target.repeat_interleave(
          self.num_parallel_samples, dim=0
      )
  
      # Note that gluonts returns empty future_observed_values.
      future_observed_values = torch.ones(
          (past_observed_values.shape[0], self.prediction_length)
      )
      observed_values = torch.cat(
          [past_observed_values, future_observed_values], dim=1
      )
      observed_values = observed_values.repeat_interleave(
          self.num_parallel_samples, dim=0
      )
  
      time_feat = torch.cat([past_time_feat, future_time_feat], dim=1)
      time_feat = time_feat.repeat_interleave(
          self.num_parallel_samples, dim=0
      )
  
      feat_static_cat = feat_static_cat.repeat_interleave(
          self.num_parallel_samples, dim=0
      )
  
      feat_static_real = feat_static_real.repeat_interleave(
          self.num_parallel_samples, dim=0
      )
  
      future_samples = []
      for t in range(self.prediction_length):
          distr = self.net(
              feat_static_cat=feat_static_cat,
              feat_static_real=feat_static_real,
              past_target=past_target,
              past_observed_values=observed_values[
                  :, t : -self.prediction_length + t
              ],
              past_time_feat=time_feat[
                  :, t : -self.prediction_length + t, :
              ],
          )
          samples = distr.sample()
          if past_target.dim() != samples.dim():
              samples = samples.unsqueeze(dim=-1)
  
          future_samples.append(samples)
          past_target = torch.cat([past_target[:, 1:], samples], dim=1)
  
      # (batch_size * num_parallel_samples, prediction_length)
      samples_out = torch.stack(future_samples, dim=1)
  
      # (batch_size, num_parallel_samples, prediction_length)
      return samples_out.reshape(
          -1, self.num_parallel_samples, self.prediction_length
      )
  
imports: from functools import partial
  from typing import Optional, Callable, List, Union
  import torch
  from torch import nn
  from torch.distributions import Categorical, MixtureSameFamily, Normal
  from gluonts.core.component import validated
  from gluonts.torch.distributions import DiscreteDistribution
  from .scaling import min_max_scaling, standard_normal_scaling
label_desc: Use image node_id 2 for calling the DeepNPTSMultiStepNetwork obj's underlying member method code with example usage: obj.forward(feat_static_cat, feat_static_real, past_target, past_observed_values, past_time_feat, future_time_feat) and returns: samples_out