class_docstr: Random Forest model (scikit-learn): https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
code: def _predict_proba_oof(self, X, y, **kwargs):
      if not self.model.bootstrap:
          raise ValueError(
              "Forest models must set `bootstrap=True` to compute out-of-fold predictions via out-of-bag predictions."
          )
  
      oob_is_not_set = (
          getattr(self.model, "oob_decision_function_", None) is None
          and getattr(self.model, "oob_prediction_", None) is None
      )
  
      if oob_is_not_set and self._daal:
          raise AssertionError(
              "DAAL forest backend does not support out-of-bag predictions."
          )
  
      # TODO: This can also be done via setting `oob_score=True` in model params,
      #  but getting the correct `pred_time_val` that way is not easy, since we can't time the internal call.
      if oob_is_not_set and self._model_supports_oob_pred_proba():
          X = self.preprocess(X)
  
          if getattr(self.model, "n_classes_", None) is not None:
              if self.model.n_outputs_ == 1:
                  self.model.n_classes_ = [self.model.n_classes_]
          from sklearn.tree._tree import DOUBLE, DTYPE
  
          X, y = self.model._validate_data(
              X, y, multi_output=True, accept_sparse="csc", dtype=DTYPE
          )
          if y.ndim == 1:
              # reshape is necessary to preserve the data contiguity against vs
              # [:, np.newaxis] that does not.
              y = np.reshape(y, (-1, 1))
          if (
              getattr(y, "dtype", None) != DOUBLE
              or not y.flags.contiguous
          ):
              y = np.ascontiguousarray(y, dtype=DOUBLE)
          if self._is_sklearn_1():
              # sklearn >= 1.0
              # TODO: Can instead do `_compute_oob_predictions` but requires post-processing. Skips scoring func.
              self.model._set_oob_score_and_attributes(X, y)
          else:
              # sklearn < 1.0
              # TODO: Remove once sklearn < 1.0 support is dropped
              self.model._set_oob_score(X, y)
          if getattr(self.model, "n_classes_", None) is not None:
              if self.model.n_outputs_ == 1:
                  self.model.n_classes_ = self.model.n_classes_[0]
  
      if (
          getattr(self.model, "oob_decision_function_", None)
          is not None
      ):
          y_oof_pred_proba = self.model.oob_decision_function_
          self.model.oob_decision_function_ = None  # save memory
      elif getattr(self.model, "oob_prediction_", None) is not None:
          y_oof_pred_proba = self.model.oob_prediction_
          self.model.oob_prediction_ = None  # save memory
      else:
          raise AssertionError(
              f"Model class {type(self.model)} does not support out-of-fold prediction generation."
          )
  
      # TODO: Regression does not return NaN for missing rows, instead it sets them to 0. This makes life hard.
      #  The below code corrects the missing rows to NaN instead of 0.
      # Don't bother if >60 trees, near impossible to have missing
      # If using 68% of data for training, chance of missing for each row is 1 in 11 billion.
      if (
          self.problem_type == REGRESSION
          and self.model.n_estimators <= 60
      ):
          from sklearn.ensemble._forest import (
              _generate_unsampled_indices,
              _get_n_samples_bootstrap,
          )
  
          n_samples = len(y)
  
          n_predictions = np.zeros(n_samples)
          n_samples_bootstrap = _get_n_samples_bootstrap(
              n_samples, self.model.max_samples
          )
          for estimator in self.model.estimators_:
              unsampled_indices = _generate_unsampled_indices(
                  estimator.random_state, n_samples, n_samples_bootstrap
              )
              n_predictions[unsampled_indices] += 1
          missing_row_mask = n_predictions == 0
          y_oof_pred_proba[missing_row_mask] = np.nan
  
      # fill missing prediction rows with average of non-missing rows
      if np.isnan(np.sum(y_oof_pred_proba)):
          if len(y_oof_pred_proba.shape) == 1:
              col_mean = np.nanmean(y_oof_pred_proba)
              y_oof_pred_proba[np.isnan(y_oof_pred_proba)] = col_mean
          else:
              col_mean = np.nanmean(y_oof_pred_proba, axis=0)
              inds = np.where(np.isnan(y_oof_pred_proba))
              y_oof_pred_proba[inds] = np.take(col_mean, inds[1])
  
      return self._convert_proba_to_unified_form(y_oof_pred_proba)
  
imports: import logging
  import math
  import os
  import pickle
  import sys
  import time
  import numpy
  from autogluon.common.features.types import R_BOOL, R_CATEGORY, R_FLOAT, R_INT
  from autogluon.common.utils.resource_utils import ResourceManager
  from autogluon.core.constants import MULTICLASS, QUANTILE, REGRESSION, SOFTCLASS
  from autogluon.core.models import AbstractModel
  from autogluon.core.utils.exceptions import NotEnoughMemoryError, TimeLimitExceeded
  from autogluon.core.utils.utils import normalize_pred_probas
  from autogluon.features.generators import LabelEncoderFeatureGenerator
  from .compilers.native import RFNativeCompiler
  from .compilers.onnx import RFOnnxCompiler
label_desc: Use image node_id 15 for calling the RFModel obj's underlying member method code with example usage: obj._predict_proba_oof(X, y) and returns: self