docstr: Unrolls the LSTM encoder over past and, if present, future data.
  
  Returns outputs and state of the encoder, plus the scale of past_target
  and a vector of static features that was constructed and fed as input
  to the encoder. All tensor arguments should have NTC layout.
docstr_tok: ["Unrolls","the","LSTM","encoder","over","past","and",",","if","present",",","future","data",".","Returns","outputs","and","state","of","the","encoder",",","plus","the","scale","of","past_target","and","a","vector","of","static","features","that","was","constructed","and","fed","as","input","to","the","encoder",".","All","tensor","arguments","should","have","NTC","layout","."]
code: def unroll_encoder_default(
      self,
      F,
      feat_static_cat: Tensor,  # (batch_size, num_features)
      feat_static_real: Tensor,  # (batch_size, num_features)
      past_time_feat: Tensor,  # (batch_size, history_length, num_features)
      past_target: Tensor,  # (batch_size, history_length, *target_shape)
      # (batch_size, history_length, *target_shape)
      past_observed_values: Tensor,
      past_is_pad: Tensor,
      future_observed_values: Optional[Tensor],
      future_time_feat: Optional[
          Tensor
      ],  # (batch_size, prediction_length, num_features)
      future_target: Optional[
          Tensor
      ],  # (batch_size, prediction_length, *target_shape)
  ) -> Tuple[Tensor, List, Tensor, Tensor, Tensor]:
      """
      Unrolls the LSTM encoder over past and, if present, future data.
  
      Returns outputs and state of the encoder, plus the scale of past_target
      and a vector of static features that was constructed and fed as input
      to the encoder. All tensor arguments should have NTC layout.
      """
  
      if future_time_feat is None or future_target is None:
          time_feat = past_time_feat.slice_axis(
              axis=1,
              begin=self.history_length - self.context_length,
              end=None,
          )
  
          is_padded_indicator = past_is_pad.slice_axis(
              axis=1,
              begin=self.history_length - self.context_length,
              end=None,
          )
  
          sequence = past_target
          sequence_length = self.history_length
          subsequences_length = self.context_length
      else:
          time_feat = F.concat(
              past_time_feat.slice_axis(
                  axis=1,
                  begin=self.history_length - self.context_length,
                  end=None,
              ),
              future_time_feat,
              dim=1,
          )
  
          is_padded_indicator = F.concat(
              past_is_pad.slice_axis(
                  axis=1,
                  begin=self.history_length - self.context_length,
                  end=None,
              ),
              F.zeros_like(future_observed_values),
              dim=1,
          )
  
          sequence = F.concat(past_target, future_target, dim=1)
          sequence_length = self.history_length + self.prediction_length
          subsequences_length = (
              self.context_length + self.prediction_length
          )
  
      # (batch_size, sub_seq_len, *target_shape, num_lags)
      lags = self.get_lagged_subsequences(
          F=F,
          sequence=sequence,
          sequence_length=sequence_length,
          indices=self.lags_seq,
          subsequences_length=subsequences_length,
      )
  
      # scale is computed on the context length last units of the past target
      # scale shape is (batch_size, 1, *target_shape)
      _, scale = self.scaler(
          past_target.slice_axis(
              axis=1, begin=-self.context_length, end=None
          ),
          past_observed_values.slice_axis(
              axis=1, begin=-self.context_length, end=None
          ),
      )
  
      # (batch_size, num_features)
      embedded_cat = self.embedder(feat_static_cat)
  
      # in addition to embedding features, use the log scale as it can help
      # prediction too
      # (batch_size, num_features + prod(target_shape))
      static_feat = F.concat(
          embedded_cat,
          feat_static_real,
          F.log(scale)
          if len(self.target_shape) == 0
          else F.log(scale.squeeze(axis=1)),
          dim=1,
      )
  
      # (batch_size, subsequences_length, num_features + 1)
      repeated_static_feat = static_feat.expand_dims(axis=1).repeat(
          axis=1, repeats=subsequences_length
      )
  
      # (batch_size, sub_seq_len, *target_shape, num_lags)
      lags_scaled = F.broadcast_div(lags, scale.expand_dims(axis=-1))
  
      # from (batch_size, sub_seq_len, *target_shape, num_lags)
      # to (batch_size, sub_seq_len, prod(target_shape) * num_lags)
      input_lags = F.reshape(
          data=lags_scaled,
          shape=(
              -1,
              subsequences_length,
              len(self.lags_seq) * prod(self.target_shape),
          ),
      )
  
      # (batch_size, sub_seq_len, input_dim)
      inputs = F.concat(
          input_lags, time_feat, repeated_static_feat, dim=-1
      )
  
      begin_state = self.rnn.begin_state(
          func=F.zeros,
          dtype=self.dtype,
          batch_size=inputs.shape[0]
          if isinstance(inputs, mx.nd.NDArray)
          else 0,
      )
      state = begin_state
      # This is a dummy computation to avoid deferred initialization error
      # when past_is_pad is not used in the computation graph in default
      # unrolling mode.
      state = [
          F.where(
              is_padded_indicator.slice_axis(
                  axis=1, begin=0, end=1
              ).repeat(repeats=self.num_cells, axis=1),
              bs,
              s,
          )
          for bs, s in zip(begin_state, state)
      ]
  
      # unroll encoder
      outputs, state = self.rnn.unroll(
          inputs=inputs,
          length=subsequences_length,
          layout="NTC",
          merge_outputs=True,
          begin_state=state,
      )
  
      # outputs: (batch_size, seq_len, num_cells)
      # state: list of (batch_size, num_cells) tensors
      # scale: (batch_size, 1, *target_shape)
      # static_feat: (batch_size, num_features + prod(target_shape))
      return outputs, state, scale, static_feat, sequence
  
imports: from typing import List, Optional, Tuple, Union, Type
  import mxnet
  import numpy
  from mxnet.gluon.contrib.rnn import VariationalDropoutCell
  from mxnet.gluon.rnn import ZoneoutCell
  from gluonts.core.component import validated
  from gluonts.itertools import prod
  from gluonts.mx import Tensor
  from gluonts.mx.block.dropout import RNNZoneoutCell, VariationalZoneoutCell
  from gluonts.mx.block.feature import FeatureEmbedder
  from gluonts.mx.block.regularization import ActivationRegularizationLoss, TemporalActivationRegularizationLoss
  from gluonts.mx.block.scaler import MeanScaler, NOPScaler
  from gluonts.mx.distribution import Distribution, DistributionOutput
  from gluonts.mx.distribution.distribution import getF
  from gluonts.mx.util import weighted_average, mx_switch
  from mxnet import autograd
label_desc: Use image node_id 8 for calling the DeepARNetwork obj's underlying member method code with example usage: obj.unroll_encoder_default(F, feat_static_cat, feat_static_real, past_time_feat, past_target, past_observed_values, past_is_pad, future_observed_values, future_time_feat, future_target) and returns: outputs,  state,  scale,  static_feat,  sequence