docstr: Predict with core.NeuralForecast.
  
  Use stored fitted `models` to predict large set of time series from DataFrame `df`.
  
  Parameters
  ----------
  df : pandas or polars DataFrame, optional (default=None)
      DataFrame with columns [`unique_id`, `ds`, `y`] and exogenous variables.
      If a DataFrame is passed, it is used to generate forecasts.
  static_df : pandas or polars DataFrame, optional (default=None)
      DataFrame with columns [`unique_id`] and static exogenous.
  futr_df : pandas or polars DataFrame, optional (default=None)
      DataFrame with [`unique_id`, `ds`] columns and `df`'s future exogenous.
  sort_df : bool (default=True)
      Sort `df` before fitting.
  verbose : bool (default=False)
      Print processing steps.
  data_kwargs : kwargs
      Extra arguments to be passed to the dataset within each model.
  
  Returns
  -------
  fcsts_df : pandas or polars DataFrame
      DataFrame with insample `models` columns for point predictions and probabilistic
      predictions for all fitted `models`.
docstr_tok: ["Predict","with","core.NeuralForecast",".","Use","stored","fitted","`","models","`","to","predict","large","set","of","time","series","from","DataFrame","`","df","`",".","Parameters","--","--","--","--","--","df",":","pandas","or","polars","DataFrame",",","optional","(","default=None",")","DataFrame","with","columns","[","`","unique_id","`",",","`","ds","`",",","`","y","`","]","and","exogenous","variables",".","If","a","DataFrame","is","passed",",","it","is","used","to","generate","forecasts",".","static_df",":","pandas","or","polars","DataFrame",",","optional","(","default=None",")","DataFrame","with","columns","[","`","unique_id","`","]","and","static","exogenous",".","futr_df",":","pandas","or","polars","DataFrame",",","optional","(","default=None",")","DataFrame","with","[","`","unique_id","`",",","`","ds","`","]","columns","and","`","df","`","'s","future","exogenous",".","sort_df",":","bool","(","default=True",")","Sort","`","df","`","before","fitting",".","verbose",":","bool","(","default=False",")","Print","processing","steps",".","data_kwargs",":","kwargs","Extra","arguments","to","be","passed","to","the","dataset","within","each","model",".","Returns","--","--","--","-","fcsts_df",":","pandas","or","polars","DataFrame","DataFrame","with","insample","`","models","`","columns","for","point","predictions","and","probabilistic","predictions","for","all","fitted","`","models","`","."]
code: def predict(
      self,
      df: Optional[DataFrame] = None,
      static_df: Optional[DataFrame] = None,
      futr_df: Optional[DataFrame] = None,
      sort_df: bool = True,
      verbose: bool = False,
      **data_kwargs,
  ):
      """Predict with core.NeuralForecast.
  
      Use stored fitted `models` to predict large set of time series from DataFrame `df`.
  
      Parameters
      ----------
      df : pandas or polars DataFrame, optional (default=None)
          DataFrame with columns [`unique_id`, `ds`, `y`] and exogenous variables.
          If a DataFrame is passed, it is used to generate forecasts.
      static_df : pandas or polars DataFrame, optional (default=None)
          DataFrame with columns [`unique_id`] and static exogenous.
      futr_df : pandas or polars DataFrame, optional (default=None)
          DataFrame with [`unique_id`, `ds`] columns and `df`'s future exogenous.
      sort_df : bool (default=True)
          Sort `df` before fitting.
      verbose : bool (default=False)
          Print processing steps.
      data_kwargs : kwargs
          Extra arguments to be passed to the dataset within each model.
  
      Returns
      -------
      fcsts_df : pandas or polars DataFrame
          DataFrame with insample `models` columns for point predictions and probabilistic
          predictions for all fitted `models`.
      """
      if (df is None) and not (hasattr(self, "dataset")):
          raise Exception(
              "You must pass a DataFrame or have one stored."
          )
  
      if not self._fitted:
          raise Exception("You must fit the model before predicting.")
  
      needed_futr_exog = self._get_needed_futr_exog()
      if needed_futr_exog:
          if futr_df is None:
              raise ValueError(
                  f"Models require the following future exogenous features: {needed_futr_exog}. "
                  "Please provide them through the `futr_df` argument."
              )
          else:
              missing = needed_futr_exog - set(futr_df.columns)
              if missing:
                  raise ValueError(
                      f"The following features are missing from `futr_df`: {missing}"
                  )
  
      # Process new dataset but does not store it.
      if df is not None:
          validate_freq(df[self.time_col], self.freq)
          dataset, uids, last_dates, _ = self._prepare_fit(
              df=df,
              static_df=static_df,
              sort_df=sort_df,
              predict_only=True,
              id_col=self.id_col,
              time_col=self.time_col,
              target_col=self.target_col,
          )
      else:
          dataset = self.dataset
          uids = self.uids
          last_dates = self.last_dates
          if verbose:
              print("Using stored dataset.")
  
      cols = []
      count_names = {"model": 0}
      for model in self.models:
          model_name = repr(model)
          count_names[model_name] = count_names.get(model_name, -1) + 1
          if count_names[model_name] > 0:
              model_name += str(count_names[model_name])
          cols += [model_name + n for n in model.loss.output_names]
  
      # Placeholder dataframe for predictions with unique_id and ds
      fcsts_df = ufp.make_future_dataframe(
          uids=uids,
          last_times=last_dates,
          freq=self.freq,
          h=self.h,
          id_col=self.id_col,
          time_col=self.time_col,
      )
  
      # Update and define new forecasting dataset
      if futr_df is None:
          futr_df = fcsts_df
      else:
          futr_orig_rows = futr_df.shape[0]
          futr_df = ufp.join(
              futr_df, fcsts_df, on=[self.id_col, self.time_col]
          )
          if futr_df.shape[0] < fcsts_df.shape[0]:
              if df is None:
                  expected_cmd = "make_future_dataframe()"
                  missing_cmd = "get_missing_future(futr_df)"
              else:
                  expected_cmd = "make_future_dataframe(df)"
                  missing_cmd = "get_missing_future(futr_df, df)"
              raise ValueError(
                  "There are missing combinations of ids and times in `futr_df`.\n"
                  f"You can run the `{expected_cmd}` method to get the expected combinations or "
                  f"the `{missing_cmd}` method to get the missing combinations."
              )
          if futr_orig_rows > futr_df.shape[0]:
              dropped_rows = futr_orig_rows - futr_df.shape[0]
              warnings.warn(
                  f"Dropped {dropped_rows:,} unused rows from `futr_df`."
              )
          if any(
              ufp.is_none(futr_df[col]).any()
              for col in needed_futr_exog
          ):
              raise ValueError("Found null values in `futr_df`")
      futr_dataset = dataset.align(
          futr_df,
          id_col=self.id_col,
          time_col=self.time_col,
          target_col=self.target_col,
      )
      self._scalers_transform(futr_dataset)
      dataset = dataset.append(futr_dataset)
  
      col_idx = 0
      fcsts = np.full(
          (self.h * len(uids), len(cols)),
          fill_value=np.nan,
          dtype=np.float32,
      )
      for model in self.models:
          old_test_size = model.get_test_size()
          model.set_test_size(self.h)  # To predict h steps ahead
          model_fcsts = model.predict(dataset=dataset, **data_kwargs)
          # Append predictions in memory placeholder
          output_length = len(model.loss.output_names)
          fcsts[:, col_idx : col_idx + output_length] = model_fcsts
          col_idx += output_length
          model.set_test_size(
              old_test_size
          )  # Set back to original value
      if self.scalers_:
          indptr = np.append(0, np.full(len(uids), self.h).cumsum())
          fcsts = self._scalers_target_inverse_transform(fcsts, indptr)
  
      # Declare predictions pd.DataFrame
      if isinstance(fcsts_df, pl_DataFrame):
          fcsts = pl_DataFrame(dict(zip(cols, fcsts.T)))
      else:
          fcsts = pd.DataFrame(fcsts, columns=cols)
      fcsts_df = ufp.horizontal_concat([fcsts_df, fcsts])
      if isinstance(fcsts_df, pd.DataFrame) and _id_as_idx():
          _warn_id_as_idx()
          fcsts_df = fcsts_df.set_index(self.id_col)
      return fcsts_df
  
imports: import os
  import pickle
  import warnings
  from copy import deepcopy
  from itertools import chain
  from typing import Any, Dict, List, Optional, Union
  import numpy
  import pandas
  import torch
  import utilsforecast.processing
  from utilsforecast.compat import DataFrame, Series, pl_DataFrame, pl_Series
  from utilsforecast.grouped_array import GroupedArray
  from utilsforecast.target_transforms import BaseTargetTransform, LocalBoxCox, LocalMinMaxScaler, LocalRobustScaler, LocalStandardScaler
  from utilsforecast.validation import validate_freq
  from .tsdataset import TimeSeriesDataset
  from neuralforecast.models import GRU, LSTM, RNN, TCN, DeepAR, DilatedRNN, MLP, NHITS, NBEATS, NBEATSx, TFT, VanillaTransformer, Informer, Autoformer, FEDformer, StemGNN, PatchTST, TimesNet
label_desc: Use image node_id 10 for calling the NeuralForecast obj's underlying member method code with example usage: obj.predict(df, static_df, futr_df, sort_df, verbose) and returns: fcsts_df