class_docstr: Base Windows
  
  Base class for all windows-based models. The forecasts are produced separately
  for each window, which are randomly sampled during training.
  
  This class implements the basic functionality for all windows-based models, including:
  - PyTorch Lightning's methods training_step, validation_step, predict_step.<br>
  - fit and predict methods used by NeuralForecast.core class.<br>
  - sampling and wrangling methods to generate windows.
class_docstr_tok: ["Base","Windows","Base","class","for","all","windows-based","models",".","The","forecasts","are","produced","separately","for","each","window",",","which","are","randomly","sampled","during","training",".","This","class","implements","the","basic","functionality","for","all","windows-based","models",",","including",":","-","PyTorch","Lightning","'s","methods","training_step",",","validation_step",",","predict_step.","<","br",">","-","fit","and","predict","methods","used","by","NeuralForecast.core","class.","<","br",">","-","sampling","and","wrangling","methods","to","generate","windows","."]
code: def predict_step(self, batch, batch_idx):
      # TODO: Hack to compute number of windows
      windows = self._create_windows(batch, step="predict")
      n_windows = len(windows["temporal"])
      y_idx = batch["y_idx"]
  
      # Number of windows in batch
      windows_batch_size = self.inference_windows_batch_size
      if windows_batch_size < 0:
          windows_batch_size = n_windows
      n_batches = int(np.ceil(n_windows / windows_batch_size))
  
      y_hats = []
      for i in range(n_batches):
          # Create and normalize windows [Ws, L+H, C]
          w_idxs = np.arange(
              i * windows_batch_size,
              min((i + 1) * windows_batch_size, n_windows),
          )
          windows = self._create_windows(
              batch, step="predict", w_idxs=w_idxs
          )
          windows = self._normalization(windows=windows, y_idx=y_idx)
  
          # Parse windows
          (
              insample_y,
              insample_mask,
              _,
              _,
              hist_exog,
              futr_exog,
              stat_exog,
          ) = self._parse_windows(batch, windows)
          windows_batch = dict(
              insample_y=insample_y,  # [Ws, L]
              insample_mask=insample_mask,  # [Ws, L]
              futr_exog=futr_exog,  # [Ws, L+H]
              hist_exog=hist_exog,  # [Ws, L]
              stat_exog=stat_exog,
          )  # [Ws, 1]
  
          # Model Predictions
          output_batch = self(windows_batch)
          # Inverse normalization and sampling
          if self.loss.is_distribution_output:
              _, y_loc, y_scale = self._inv_normalization(
                  y_hat=output_batch[0],
                  temporal_cols=batch["temporal_cols"],
                  y_idx=y_idx,
              )
              distr_args = self.loss.scale_decouple(
                  output=output_batch, loc=y_loc, scale=y_scale
              )
              _, sample_mean, quants = self.loss.sample(
                  distr_args=distr_args
              )
              y_hat = torch.concat((sample_mean, quants), axis=2)
  
              if self.loss.return_params:
                  distr_args = torch.stack(distr_args, dim=-1)
                  distr_args = torch.reshape(
                      distr_args, (len(windows["temporal"]), self.h, -1)
                  )
                  y_hat = torch.concat((y_hat, distr_args), axis=2)
          else:
              y_hat, _, _ = self._inv_normalization(
                  y_hat=output_batch,
                  temporal_cols=batch["temporal_cols"],
                  y_idx=y_idx,
              )
          y_hats.append(y_hat)
      y_hat = torch.cat(y_hats, dim=0)
      return y_hat
  
imports: import random
  import warnings
  import numpy
  import torch
  import torch.nn
  import pytorch_lightning
  from pytorch_lightning.callbacks import TQDMProgressBar
  from pytorch_lightning.callbacks.early_stopping import EarlyStopping
  from ._scalers import TemporalNorm
  from ..tsdataset import TimeSeriesDataModule
  from ..utils import get_indexer_raise_missing
label_desc: Use image node_id 14 for calling the BaseWindows obj's underlying member method code with example usage: obj.predict_step(batch, batch_idx) and returns: y_hat