class_docstr: Abstract base class for Gradient Boosting.
class_docstr_tok: ["Abstract","base","class","for","Gradient","Boosting","."]
docstr: Fit another stage of ``_n_classes`` trees to the boosting model.
code: def _fit_stage(
      self,
      i,
      X,
      y,
      raw_predictions,
      sample_weight,
      sample_mask,
      random_state,
      X_csc=None,
      X_csr=None,
  ):
      """Fit another stage of ``_n_classes`` trees to the boosting model."""
  
      assert sample_mask.dtype == bool
      loss = self._loss
      original_y = y
  
      # Need to pass a copy of raw_predictions to negative_gradient()
      # because raw_predictions is partially updated at the end of the loop
      # in update_terminal_regions(), and gradients need to be evaluated at
      # iteration i - 1.
      raw_predictions_copy = raw_predictions.copy()
  
      for k in range(loss.K):
          if loss.is_multi_class:
              y = np.array(original_y == k, dtype=np.float64)
  
          residual = loss.negative_gradient(
              y, raw_predictions_copy, k=k, sample_weight=sample_weight
          )
  
          # induce regression tree on residuals
          tree = DecisionTreeRegressor(
              criterion=self.criterion,
              splitter="best",
              max_depth=self.max_depth,
              min_samples_split=self.min_samples_split,
              min_samples_leaf=self.min_samples_leaf,
              min_weight_fraction_leaf=self.min_weight_fraction_leaf,
              min_impurity_decrease=self.min_impurity_decrease,
              max_features=self.max_features,
              max_leaf_nodes=self.max_leaf_nodes,
              random_state=random_state,
              ccp_alpha=self.ccp_alpha,
          )
  
          if self.subsample < 1.0:
              # no inplace multiplication!
              sample_weight = sample_weight * sample_mask.astype(
                  np.float64
              )
  
          X = X_csr if X_csr is not None else X
          tree.fit(
              X,
              residual,
              sample_weight=sample_weight,
              check_input=False,
          )
  
          # update tree leaves
          loss.update_terminal_regions(
              tree.tree_,
              X,
              y,
              residual,
              raw_predictions,
              sample_weight,
              sample_mask,
              learning_rate=self.learning_rate,
              k=k,
          )
  
          # add tree to ensemble
          self.estimators_[i, k] = tree
  
      return raw_predictions
  
imports: import warnings
  from abc import ABCMeta, abstractmethod
  from numbers import Integral, Real
  from time import time
  import numpy
  from scipy.sparse import csc_matrix, csr_matrix, issparse
  from ..base import ClassifierMixin, RegressorMixin, _fit_context, is_classifier
  from ..exceptions import NotFittedError
  from ..model_selection import train_test_split
  from ..tree import DecisionTreeRegressor
  from ..tree._tree import DOUBLE, DTYPE
  from ..utils import check_array, check_random_state, column_or_1d
  from ..utils._param_validation import HasMethods, Interval, StrOptions
  from ..utils.multiclass import check_classification_targets
  from ..utils.validation import _check_sample_weight, check_is_fitted
  from .None import _gb_losses
  from ._base import BaseEnsemble
  from ._gradient_boosting import _random_sample_mask, predict_stage, predict_stages
label_desc: Use image node_id 3 for calling the BaseGradientBoosting obj's underlying member method code with example usage: obj._fit_stage(i, X, y, raw_predictions, sample_weight, sample_mask, random_state, X_csc, X_csr) and returns: raw_predictions