docstr: Make predictions based on datasource with the same features as the ones used for fitting
  
  :param ds: Predictions are generate from it
  :param arg: Any additional arguments used in predicting
  
  :returns: A dataframe cotaining the decoded predictions and (depending on the args) additional information such as the probabilites for each target class
code: def __call__(
      self,
      ds: EncodedDs,
      args: PredictionArguments = PredictionArguments(),
  ) -> pd.DataFrame:
      """
      Make predictions based on datasource with the same features as the ones used for fitting
  
      :param ds: Predictions are generate from it
      :param arg: Any additional arguments used in predicting
  
      :returns: A dataframe cotaining the decoded predictions and (depending on the args) additional information such as the probabilites for each target class
      """  # noqa
      self.model = self.model.eval()
      decoded_predictions: List[object] = []
      all_probs: List[List[float]] = []
      rev_map = {}
  
      with torch.no_grad():
          for idx, (X, Y) in enumerate(ds):
              X = X.to(self.model.device)
              Yh = self._net_call(X)
              Yh = torch.unsqueeze(Yh, 0) if len(Yh.shape) < 2 else Yh
  
              kwargs = {}
              for dep in self.target_encoder.dependencies:
                  kwargs["dependency_data"] = {
                      dep: ds.data_frame.iloc[idx][[dep]].values
                  }
  
              if args.predict_proba and self.supports_proba:
                  (
                      decoded_prediction,
                      probs,
                      rev_map,
                  ) = self.target_encoder.decode_probabilities(
                      Yh, **kwargs
                  )
                  all_probs.append(probs)
              else:
                  decoded_prediction = self.target_encoder.decode(
                      Yh, **kwargs
                  )
  
              decoded_predictions.extend(decoded_prediction)
  
          ydf = pd.DataFrame({"prediction": decoded_predictions})
  
          if args.predict_proba and self.supports_proba:
              raw_predictions = np.array(all_probs).squeeze(axis=1)
  
              for idx, label in enumerate(rev_map.values()):
                  ydf[f"__mdb_proba_{label}"] = raw_predictions[:, idx]
  
          return ydf
  
imports: import time
  from copy import deepcopy
  from collections import deque
  from typing import Dict, List, Optional
  import torch
  import numpy
  import pandas
  from torch import nn
  import torch_optimizer
  from sklearn.metrics import r2_score
  from torch.cuda.amp import GradScaler
  from torch.utils.data import DataLoader
  from torch.nn.modules.loss import MSELoss
  from torch.optim.optimizer import Optimizer
  from type_infer.dtype import dtype
  from lightwood.helpers.log import log
  from lightwood.encoder.base import BaseEncoder
  from lightwood.helpers.torch import LightwoodAutocast
  from lightwood.data.encoded_ds import EncodedDs
  from lightwood.mixer.base import BaseMixer
  from lightwood.mixer.helpers.ar_net import ArNet
  from lightwood.mixer.helpers.default_net import DefaultNet
  from lightwood.api.types import PredictionArguments
  from lightwood.mixer.helpers.transform_corss_entropy_loss import TransformCrossEntropyLoss
label_desc: Use image node_id 13 for calling the Neural obj's underlying member method code with example usage: obj.__call__(ds, args) and returns: ydf