class_docstr: The class object for the Random Forest Plus (RF+) estimator, which can
  be used as a prediction model or interpreted via generalized
  mean decrease in impurity (MDI+). For more details, refer to [paper].
  
  Parameters
  ----------
  rf_model: scikit-learn random forest object or None
      The RF model to be used to build RF+. If None, then a new
      RandomForestRegressor() or RandomForestClassifier() is instantiated.
  prediction_model: A PartialPredictionModelBase object, scikit-learn type estimator, or "auto"
      The prediction model to be used for making (full and partial) predictions
      using the block transformed data.
      If value is set to "auto", then a default is chosen as follows:
       - For RandomForestPlusRegressor, RidgeRegressorPPM is used.
       - For RandomForestPlusClassifier, LogisticClassifierPPM is used.
  sample_split: string in {"loo", "oob", "inbag"} or None
      The sample splitting strategy to be used for fitting RF+. If "oob",
      RF+ is trained on the out-of-bag data. If "inbag", RF+ is trained on the
      in-bag data. Otherwise, RF+ is trained on the full training data.
  include_raw: bool
      Flag for whether to augment the local decision stump features extracted
      from the RF model with the original features.
  drop_features: bool
      Flag for whether to use an intercept model for the partial predictions
      on a given feature if a tree does not have any nodes that split on it,
      or to use a model on the raw feature (if include_raw is True).
  add_transformers: list of BlockTransformerBase objects or None
      Additional block transformers (if any) to include in the RF+ model.
  center: bool
      Flag for whether to center the transformed data in the transformers.
  normalize: bool
      Flag for whether to rescale the transformed data to have unit
      variance in the transformers.
docstr: Fit (or train) Random Forest Plus (RF+) prediction model.
  
  Parameters
  ----------
  X: ndarray of shape (n_samples, n_features)
      The covariate matrix.
  y: ndarray of shape (n_samples, n_targets)
      The observed responses.
  sample_weight: array-like of shape (n_samples,) or None
      Sample weights to use in random forest fit.
      If None, samples are equally weighted.
  **kwargs:
      Additional arguments to pass to self.prediction_model.fit()
docstr_tok: ["Fit","(","or","train",")","Random","Forest","Plus","(","RF+",")","prediction","model",".","Parameters","--","--","--","--","--","X",":","ndarray","of","shape","(","n_samples",",","n_features",")","The","covariate","matrix",".","y",":","ndarray","of","shape","(","n_samples",",","n_targets",")","The","observed","responses",".","sample_weight",":","array-like","of","shape","(","n_samples",",",")","or","None","Sample","weights","to","use","in","random","forest","fit",".","If","None",",","samples","are","equally","weighted",".","*","*","kwargs",":","Additional","arguments","to","pass","to","self.prediction_model.fit","(",")"]
code: def fit(self, X, y, sample_weight=None, **kwargs):
      """
      Fit (or train) Random Forest Plus (RF+) prediction model.
  
      Parameters
      ----------
      X: ndarray of shape (n_samples, n_features)
          The covariate matrix.
      y: ndarray of shape (n_samples, n_targets)
          The observed responses.
      sample_weight: array-like of shape (n_samples,) or None
          Sample weights to use in random forest fit.
          If None, samples are equally weighted.
      **kwargs:
          Additional arguments to pass to self.prediction_model.fit()
  
      """
      self.transformers_ = []
      self.estimators_ = []
      self._tree_random_states = []
      self.prediction_score_ = None
      self.mdi_plus_ = None
      self.mdi_plus_scores_ = None
      self.feature_names_ = None
      self._n_samples_train = X.shape[0]
  
      if isinstance(X, pd.DataFrame):
          self.feature_names_ = list(X.columns)
          X_array = X.values
      elif isinstance(X, np.ndarray):
          X_array = X
      else:
          raise ValueError(
              "Input X must be a pandas DataFrame or numpy array."
          )
      if isinstance(y, pd.DataFrame):
          y = y.values.ravel()
      elif not isinstance(y, np.ndarray):
          raise ValueError(
              "Input y must be a pandas DataFrame or numpy array."
          )
  
      # fit random forest
      n_samples = X.shape[0]
      self.rf_model.fit(X, y, sample_weight=sample_weight)
      # onehot encode multiclass response for GlmClassiferPPM
      if isinstance(self.prediction_model, GlmClassifierPPM):
          self._multi_class = False
          if len(np.unique(y)) > 2:
              self._multi_class = True
              self._y_encoder = OneHotEncoder()
              y = self._y_encoder.fit_transform(
                  y.reshape(-1, 1)
              ).toarray()
      # fit model for each tree
      all_full_preds = []
      for tree_model in self.rf_model.estimators_:
          # get transformer
          if self.add_transformers is None:
              if self.include_raw:
                  transformer = MDIPlusDefaultTransformer(
                      tree_model, drop_features=self.drop_features
                  )
              else:
                  transformer = TreeTransformer(tree_model)
          else:
              if self.include_raw:
                  base_transformer_list = [
                      TreeTransformer(tree_model),
                      IdentityTransformer(),
                  ]
              else:
                  base_transformer_list = [TreeTransformer(tree_model)]
              transformer = CompositeTransformer(
                  base_transformer_list + self.add_transformers,
                  drop_features=self.drop_features,
              )
          # fit transformer
          blocked_data = transformer.fit_transform(
              X_array, center=self.center, normalize=self.normalize
          )
          # do sample split
          (
              train_blocked_data,
              test_blocked_data,
              y_train,
              y_test,
              test_indices,
          ) = _get_sample_split_data(
              blocked_data,
              y,
              tree_model.random_state,
              self.sample_split,
          )
          # fit prediction model
          if (
              train_blocked_data.get_all_data().shape[1] != 0
          ):  # if tree has >= 1 split
              self.prediction_model.fit(
                  train_blocked_data.get_all_data(), y_train, **kwargs
              )
              self.estimators_.append(
                  copy.deepcopy(self.prediction_model)
              )
              self.transformers_.append(copy.deepcopy(transformer))
              self._tree_random_states.append(tree_model.random_state)
  
              # get full predictions
              pred_func = self._get_pred_func()
              full_preds = pred_func(test_blocked_data.get_all_data())
              full_preds_n = (
                  np.empty(n_samples)
                  if full_preds.ndim == 1
                  else np.empty((n_samples, full_preds.shape[1]))
              )
              full_preds_n[:] = np.nan
              full_preds_n[test_indices] = full_preds
              all_full_preds.append(full_preds_n)
  
      # compute prediction accuracy on internal sample split
      full_preds = np.nanmean(all_full_preds, axis=0)
      if self._task == "regression":
          pred_score = r2_score(y, full_preds)
          pred_score_name = "r2"
      elif self._task == "classification":
          if full_preds.shape[1] == 2:
              pred_score = roc_auc_score(
                  y, full_preds[:, 1], multi_class="ovr"
              )
          else:
              pred_score = roc_auc_score(
                  y, full_preds, multi_class="ovr"
              )
          pred_score_name = "auroc"
      self.prediction_score_ = pd.DataFrame(
          {pred_score_name: [pred_score]}
      )
      self._full_preds = full_preds
  
imports: import copy
  import numpy
  import pandas
  from sklearn.base import BaseEstimator, RegressorMixin, ClassifierMixin
  from sklearn.utils import check_array
  from sklearn.utils.validation import check_is_fitted
  from sklearn.metrics import r2_score, roc_auc_score, log_loss
  from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
  from sklearn.preprocessing import OneHotEncoder
  from imodels.importance.block_transformers import MDIPlusDefaultTransformer, TreeTransformer, CompositeTransformer, IdentityTransformer
  from imodels.importance.ppms import PartialPredictionModelBase, GlmClassifierPPM, RidgeRegressorPPM, LogisticClassifierPPM
  from imodels.importance.mdi_plus import ForestMDIPlus, _get_default_sample_split, _validate_sample_split, _get_sample_split_data
label_desc: Use image node_id 2 for calling the _RandomForestPlus obj's underlying member method code with example usage: obj.fit(X, y, sample_weight) without return types