class_docstr: Parameters
  ----------
  seasonality : int
      Length of seasonality
  seasonality_sm_input : float
      float value between [0, 1], applicable only if `seasonality` > 1. A larger value puts
      more weight on the current seasonality.
      If None, the model will estimate this value.
  level_sm_input : float
      float value between [0.0001, 1]. A larger value puts more weight on the current level.
      If None, the model will estimate this value.
class_docstr_tok: ["Parameters","--","--","--","--","--","seasonality",":","int","Length","of","seasonality","seasonality_sm_input",":","float","float","value","between","[","0",",","1","]",",","applicable","only","if","`","seasonality","`",">","1",".","A","larger","value","puts","more","weight","on","the","current","seasonality",".","If","None",",","the","model","will","estimate","this","value",".","level_sm_input",":","float","float","value","between","[","0.0001",",","1","]",".","A","larger","value","puts","more","weight","on","the","current","level",".","If","None",",","the","model","will","estimate","this","value","."]
docstr: Vectorized version of prediction math
docstr_tok: ["Vectorized","version","of","prediction","math"]
code: def predict(
      self,
      posterior_estimates,
      df,
      training_meta,
      prediction_meta,
      include_error=False,
      **kwargs,
  ):
      """Vectorized version of prediction math"""
      ################################################################
      # Prediction Attributes
      ################################################################
      # n_forecast_steps = prediction_meta[PredictionMetaKeys.FUTURE_STEPS.value]
      start = prediction_meta[PredictionMetaKeys.START_INDEX.value]
      trained_len = training_meta[TrainingMetaKeys.NUM_OF_OBS.value]
      full_len = prediction_meta[PredictionMetaKeys.END_INDEX.value]
  
      ################################################################
      # Model Attributes
      ################################################################
      model = deepcopy(posterior_estimates)
      for k, v in model.items():
          model[k] = torch.from_numpy(v)
  
      # We can pull any arbitrary value from teh dictionary because we hold the
      # safe assumption: the length of the first dimension is always the number of samples
      # thus can be safely used to determine `num_sample`. If predict_method is anything
      # other than full, the value here should be 1
      arbitrary_posterior_value = list(model.values())[0]
      num_sample = arbitrary_posterior_value.shape[0]
  
      # seasonality components
      seasonality_levels = model.get(
          SeasonalitySamplingParameters.SEASONALITY_LEVELS.value
      )
      seasonality_smoothing_factor = model.get(
          SeasonalitySamplingParameters.SEASONALITY_SMOOTHING_FACTOR.value
      )
  
      # trend components
      level_smoothing_factor = model.get(
          BaseSamplingParameters.LEVEL_SMOOTHING_FACTOR.value
      )
      local_trend_levels = model.get(
          BaseSamplingParameters.LOCAL_TREND_LEVELS.value
      )
      residual_sigma = model.get(
          BaseSamplingParameters.RESIDUAL_SIGMA.value
      )
  
      ################################################################
      # Seasonality Component
      ################################################################
  
      # calculate seasonality component
      if self._seasonality > 1:
          if full_len <= seasonality_levels.shape[1]:
              seasonal_component = seasonality_levels[:, :full_len]
          else:
              seasonality_forecast_length = (
                  full_len - seasonality_levels.shape[1]
              )
              seasonality_forecast_matrix = torch.zeros(
                  (num_sample, seasonality_forecast_length),
                  dtype=torch.double,
              )
              seasonal_component = torch.cat(
                  (seasonality_levels, seasonality_forecast_matrix),
                  dim=1,
              )
      else:
          seasonal_component = torch.zeros(
              (num_sample, full_len), dtype=torch.double
          )
  
      ################################################################
      # Trend Component
      ################################################################
  
      # calculate level component.
      # However, if predicted end of period > training period, update with out-of-samples forecast
      if full_len <= trained_len:
          trend_component = local_trend_levels[:, :full_len]
          # in-sample error are iids
          if include_error:
              error_value = np.random.normal(
                  loc=0,
                  scale=residual_sigma.unsqueeze(-1),
                  size=trend_component.shape,
              )
  
              error_value = torch.from_numpy(error_value).double()
              trend_component += error_value
      else:
          trend_component = local_trend_levels
          trend_forecast_length = full_len - trained_len
          trend_forecast_init = torch.zeros(
              (num_sample, trend_forecast_length), dtype=torch.double
          )
          # in-sample error are iids
          if include_error:
              error_value = np.random.normal(
                  loc=0,
                  scale=residual_sigma.unsqueeze(-1),
                  size=trend_component.shape,
              )
  
              error_value = torch.from_numpy(error_value).double()
              trend_component += error_value
  
          trend_component = torch.cat(
              (trend_component, trend_forecast_init), dim=1
          )
  
          last_local_trend_level = local_trend_levels[:, -1]
  
          for idx in range(trained_len, full_len):
              trend_component[:, idx] = last_local_trend_level
  
              if include_error:
                  error_value = np.random.normal(
                      scale=residual_sigma, size=num_sample
                  )
                  error_value = torch.from_numpy(error_value).double()
                  trend_component[:, idx] += error_value
  
              new_local_trend_level = (
                  level_smoothing_factor * trend_component[:, idx]
                  + (1 - level_smoothing_factor)
                  * last_local_trend_level
              )
  
              if (
                  self._seasonality > 1
                  and idx + self._seasonality < full_len
              ):
                  seasonal_component[:, idx + self._seasonality] = (
                      seasonality_smoothing_factor.flatten()
                      * (
                          trend_component[:, idx]
                          + seasonal_component[:, idx]
                          - new_local_trend_level
                      )
                      + (1 - seasonality_smoothing_factor.flatten())
                      * seasonal_component[:, idx]
                  )
  
              last_local_trend_level = new_local_trend_level
  
      ################################################################
      # Combine Components
      ################################################################
  
      # trim component with right start index
      trend_component = trend_component[:, start:]
      seasonal_component = seasonal_component[:, start:]
  
      # sum components
      pred_array = trend_component + seasonal_component
  
      pred_array = pred_array.numpy()
      trend_component = trend_component.numpy()
      seasonal_component = seasonal_component.numpy()
  
      out = {
          PredictionKeys.PREDICTION.value: pred_array,
          PredictionKeys.TREND.value: trend_component,
          PredictionKeys.SEASONALITY.value: seasonal_component,
      }
  
      return out
  
imports: import numpy
  from copy import deepcopy
  import torch
  from enum import Enum
  from ..constants.constants import PredictionKeys, TrainingMetaKeys, PredictionMetaKeys
  from ..exceptions import IllegalArgument, DataInputException
  from .model_template import ModelTemplate
  from ..estimators.stan_estimator import StanEstimatorMCMC, StanEstimatorMAP
  from ..utils.features import moving_average
label_desc: Use image node_id 7 for calling the ETSModel obj's underlying member method code with example usage: obj.predict(posterior_estimates, df, training_meta, prediction_meta, include_error) and returns: out