class_docstr: Base Stochastic Gradient Tree (SGT) class.
  
  This class defines the main characteristics that are shared by the different SGT
  implementations.
class_docstr_tok: ["Base","Stochastic","Gradient","Tree","(","SGT",")","class",".","This","class","defines","the","main","characteristics","that","are","shared","by","the","different","SGT","implementations","."]
code: def learn_one(self, x, y, *, w=1.0):
      self._n_observations += w
  
      """ Update Stochastic Gradient Tree with a single instance. """
      y_true_trs = self._target_transform(y)
  
      p_node = None
      node = None
      if not isinstance(self._root, SGTLeaf):
          path = iter(self._root.walk(x, until_leaf=False))
          while True:
              aux = next(path, None)
              if aux is None:
                  break
              p_node = node
              node = aux
      else:
          node = self._root
  
      # A leaf could not be reached in a single attempt let's deal with that
      if isinstance(node, NumericBinaryBranch) or isinstance(
          node, NominalMultiwayBranch
      ):
          while True:
              # Split node encountered a previously unseen categorical value (in a multi-way
              #  test), so there is no branch to sort the instance to
              if node.max_branches() == -1 and node.feature in x:
                  # Create a new branch to the new categorical value
                  leaf = SGTLeaf(
                      depth=node.depth + 1,
                      split_params=node.stats.copy(),
                  )
                  #
                  node.add_child(x[node.feature], leaf)
                  node = leaf
              # The split feature is missing in the instance. Hence, we pass the new example
              # to the most traversed path in the current subtree
              else:
                  _, node = node.most_common_path()
                  # And we keep trying to reach a leaf
                  if isinstance(node, DTBranch):
                      node = node.traverse(x, until_leaf=False)
              # Once a leaf is reached, the traversal can stop
              if isinstance(node, SGTLeaf):
                  break
  
          y_pred_raw = self.loss_func.transfer(node.prediction())
          grad_hess = self.loss_func.compute_derivatives(
              y_true_trs, y_pred_raw
          )
          node.update(x, grad_hess, self, w)
      else:  # Node is a leaf
          y_pred_raw = self.loss_func.transfer(node.prediction())
          grad_hess = self.loss_func.compute_derivatives(
              y_true_trs, y_pred_raw
          )
          node.update(x, grad_hess, self, w)
  
          if (
              node.total_weight - node.last_split_attempt_at
              < self.grace_period
          ):
              return
  
          # Update split attempt data
          node.last_split_attempt_at = node.total_weight
  
          # If the maximum depth is reached, attempt to apply a "null split", i.e., update the
          # prediction value
          if node.depth >= self.max_depth:
              # Null split: update the prediction using the new gradient information
              best_split = BranchFactory()
              best_split.merit = GradHessMerit()
              best_split.merit.delta_pred = node.delta_prediction(
                  node.update_stats.mean, self.lambda_value
              )
              dlms = node.update_stats.delta_loss_mean_var(
                  best_split.merit.delta_pred
              )
              best_split.merit.loss_mean = dlms.mean.get()
              best_split.merit.loss_var = dlms.get()
          else:  # Proceed with the standard split attempt procedure
              best_split = node.find_best_split(self)
  
          p = self._compute_p_value(best_split.merit, node.total_weight)
  
          if p < self.delta and best_split.merit.loss_mean < 0:
              p_branch = (
                  p_node.branch_no(x)
                  if isinstance(p_node, DTBranch)
                  else None
              )
              node.apply_split(best_split, p_node, p_branch, self)
  
imports: from __future__ import annotations
  import abc
  import math
  from scipy.stats import f
  from river import base, tree
  from .losses import BinaryCrossEntropyLoss, SquaredErrorLoss
  from .nodes.branch import DTBranch, NominalMultiwayBranch, NumericBinaryBranch
  from .nodes.sgt_nodes import SGTLeaf
  from .utils import BranchFactory, GradHessMerit
label_desc: Use image node_id 3 for calling the StochasticGradientTree obj's underlying member method code with example usage: obj.learn_one(x, y) without return types