code: def _fit(
      self,
      X,
      y,
      sample_weight=None,
      check_input=True,
      missing_values_in_feature_mask=None,
  ):
      ivy.seed(seed_value=self.random_state)
      n_samples, self.n_features_in_ = X.shape
      y = ivy.atleast_1d(y)
      if y.ndim == 1:
          y = ivy.reshape(y, (-1, 1))
      self.n_outputs_ = y.shape[1]
      y = ivy.copy.copy(y)
      self.classes_ = []
      self.n_classes_ = []
      if self.class_weight is not None:
          ivy.copy.copy(y)
      y_encoded = ivy.zeros(y.shape, dtype=ivy.int32)
  
      for k in range(self.n_outputs_):
          classes_k, y_encoded[:, k] = ivy.unique_inverse(y[:, k])
          self.classes_.append(classes_k)
          self.n_classes_.append(classes_k.shape[0])
      y = y_encoded
  
      self.n_classes_ = ivy.array(self.n_classes_, dtype="int64")
  
      y = ivy.array(y, dtype="float32")
      max_depth = (
          ivy.iinfo(ivy.int32).max
          if self.max_depth is None
          else self.max_depth
      )
  
      if isinstance(self.min_samples_leaf, numbers.Integral):
          min_samples_leaf = self.min_samples_leaf
      else:
          min_samples_leaf = int(
              ivy.ceil(self.min_samples_leaf * n_samples)
          )
  
      if isinstance(self.min_samples_split, numbers.Integral):
          min_samples_split = self.min_samples_split
      else:
          min_samples_split = int(
              ivy.ceil(self.min_samples_split * n_samples)
          )
          min_samples_split = max(2, min_samples_split)
      min_samples_split = max(min_samples_split, 2 * min_samples_leaf)
      if self.max_features is None:  # todo: other cases
          max_features = self.n_features_in_
      self.max_features_ = max_features
      assert (
          len(y) == n_samples
      ), "Number of labels does not match number of samples"
  
      if sample_weight is None:
          min_weight_leaf = self.min_weight_fraction_leaf * n_samples
      else:
          min_weight_leaf = self.min_weight_fraction_leaf * ivy.sum(
              sample_weight
          )
  
      self.n_classes_ = ivy.array(self.n_classes_, dtype=ivy.int64)
  
      criterion = self.criterion
      if not isinstance(criterion, Criterion):
          criterion = Gini(self.n_outputs_, self.n_classes_)
      else:
          criterion = copy.deepcopy(criterion)
      splitter = self.splitter
      monotonic_cst = None
  
      if not isinstance(self.splitter, Splitter):
          splitter = BestSplitter(
              criterion,
              self.max_features_,
              min_samples_leaf,
              min_weight_leaf,
              self.random_state,
              monotonic_cst,
          )
      self.tree_ = Tree(
          self.n_features_in_, self.n_classes_, self.n_outputs_
      )
      builder = DepthFirstTreeBuilder(
          splitter,
          min_samples_split,
          min_samples_leaf,
          min_weight_leaf,
          max_depth,
          self.min_impurity_decrease,
      )
      builder.build(
          self.tree_,
          X,
          y,
          sample_weight,
          missing_values_in_feature_mask,
      )
      if self.n_outputs_ == 1:
          self.n_classes_ = self.n_classes_[0]
          self.classes_ = self.classes_[0]
      self._prune_tree()
      return self
  
imports: from abc import ABCMeta, abstractmethod
  from ..base import BaseEstimator, ClassifierMixin, MultiOutputMixin
  import copy
  from ._criterion import Gini, Criterion
  from ._splitter import BestSplitter, Splitter
  from ._tree import DepthFirstTreeBuilder, Tree
  import ivy
  import numbers
label_desc: Use image node_id 4 for calling the BaseDecisionTree obj's underlying member method code with example usage: obj._fit(X, y, sample_weight, check_input, missing_values_in_feature_mask) and returns: self