class_docstr: Random Forest model (scikit-learn): https://scikit-learn.org/stable/modules/generated/sklearn.ensemble.RandomForestClassifier.html
code: def _fit(
      self,
      X,
      y,
      num_cpus=-1,
      time_limit=None,
      sample_weight=None,
      **kwargs,
  ):
      time_start = time.time()
  
      model_cls = self._get_model_type()
  
      max_memory_usage_ratio = self.params_aux["max_memory_usage_ratio"]
      params = self._get_model_params()
      if "n_jobs" not in params:
          params["n_jobs"] = num_cpus
      n_estimators_final = params["n_estimators"]
  
      n_estimators_minimum = min(40, n_estimators_final)
      n_estimators_test = min(
          4, max(1, math.floor(n_estimators_minimum / 5))
      )
  
      X = self.preprocess(X)
      n_estimator_increments = [n_estimators_final]
  
      num_trees_per_estimator = self._get_num_trees_per_estimator()
      bytes_per_estimator = (
          num_trees_per_estimator * len(X) / 60000 * 1e6
      )  # Underestimates by 3x on ExtraTrees
      expected_memory_usage = self._expected_mem_usage(
          n_estimators_final, bytes_per_estimator
      )
  
      if n_estimators_final > n_estimators_test * 2:
          if self.problem_type == MULTICLASS:
              n_estimator_increments = [
                  n_estimators_test,
                  n_estimators_final,
              ]
              params["warm_start"] = True
          else:
              if expected_memory_usage > (
                  0.05 * max_memory_usage_ratio
              ):  # Somewhat arbitrary, consider finding a better value, should it scale by cores?
                  # Causes ~10% training slowdown, so try to avoid if memory is not an issue
                  n_estimator_increments = [
                      n_estimators_test,
                      n_estimators_final,
                  ]
                  params["warm_start"] = True
  
      params["n_estimators"] = n_estimator_increments[0]
      if self._daal:
          if params.get("warm_start", False):
              params["warm_start"] = False
          # FIXME: This is inefficient but sklearnex doesn't support computing oob_score after training
          params["oob_score"] = True
  
      model = model_cls(**params)
  
      time_train_start = time.time()
      for i, n_estimators in enumerate(n_estimator_increments):
          if i != 0:
              if params.get("warm_start", False):
                  model.n_estimators = n_estimators
              else:
                  params["n_estimators"] = n_estimators
                  model = model_cls(**params)
          model = model.fit(X, y, sample_weight=sample_weight)
          if (i == 0) and (len(n_estimator_increments) > 1):
              time_elapsed = max(
                  time.time() - time_train_start, 0.001
              )  # avoid it being too small and being truncated to 0
              model_size_bytes = 0
              for (
                  estimator
              ) in (
                  model.estimators_
              ):  # Uses far less memory than pickling the entire forest at once
                  model_size_bytes += sys.getsizeof(
                      pickle.dumps(estimator)
                  )
              expected_final_model_size_bytes = model_size_bytes * (
                  n_estimators_final / model.n_estimators
              )
              available_mem = (
                  ResourceManager.get_available_virtual_mem()
              )
              model_memory_ratio = (
                  expected_final_model_size_bytes / available_mem
              )
  
              ideal_memory_ratio = 0.15 * max_memory_usage_ratio
              n_estimators_ideal = min(
                  n_estimators_final,
                  math.floor(
                      ideal_memory_ratio
                      / model_memory_ratio
                      * n_estimators_final
                  ),
              )
  
              if n_estimators_final > n_estimators_ideal:
                  if n_estimators_ideal < n_estimators_minimum:
                      logger.warning(
                          f"\tWarning: Model is expected to require {round(model_memory_ratio*100, 2)}% of available memory..."
                      )
                      raise NotEnoughMemoryError  # don't train full model to avoid OOM error
                  logger.warning(
                      f"\tWarning: Reducing model 'n_estimators' from {n_estimators_final} -> {n_estimators_ideal} due to low memory. Expected memory usage reduced from {round(model_memory_ratio*100, 2)}% -> {round(ideal_memory_ratio*100, 2)}% of available memory..."
                  )
  
              if time_limit is not None:
                  time_expected = (
                      time_train_start
                      - time_start
                      + (
                          time_elapsed
                          * n_estimators_ideal
                          / n_estimators
                      )
                  )
                  n_estimators_time = math.floor(
                      (time_limit - time_train_start + time_start)
                      * n_estimators
                      / time_elapsed
                  )
                  if n_estimators_time < n_estimators_ideal:
                      if n_estimators_time < n_estimators_minimum:
                          logger.warning(
                              f"\tWarning: Model is expected to require {round(time_expected, 1)}s to train, which exceeds the maximum time limit of {round(time_limit, 1)}s, skipping model..."
                          )
                          raise TimeLimitExceeded
                      logger.warning(
                          f"\tWarning: Reducing model 'n_estimators' from {n_estimators_ideal} -> {n_estimators_time} due to low time. Expected time usage reduced from {round(time_expected, 1)}s -> {round(time_limit, 1)}s..."
                      )
                      n_estimators_ideal = n_estimators_time
  
              for j in range(len(n_estimator_increments)):
                  if n_estimator_increments[j] > n_estimators_ideal:
                      n_estimator_increments[j] = n_estimators_ideal
      if self._daal and model.criterion != "entropy":
          # TODO: entropy is not accelerated by sklearnex, need to not set estimators_ to None to avoid crash
          # This reduces memory usage / disk usage.
          model.estimators_ = None
      self.model = model
      self.params_trained["n_estimators"] = self.model.n_estimators
  
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 10 for calling the RFModel obj's underlying member method code with example usage: obj._fit(X, y, num_cpus, time_limit, sample_weight) without return types