class_docstr: Node that splits the data in a Hoeffding Adaptive Tree.
  
  Parameters
  ----------
  stats
      Class observations
  adwin_delta
      The delta parameter of ADWIN.
  children
      Sequence of children nodes of this branch.
  attributes
      Other parameters passed to the split node.
code: def learn_one(
      self, x, y, *, w=1.0, tree=None, parent=None, parent_branch=None
  ):
      leaf = super().traverse(x, until_leaf=True)
      aux = leaf.prediction(x, tree=tree)
      y_pred = max(aux, key=aux.get) if aux else None
      detec_in = 0 if y == y_pred else 1
  
      # Update stats as traverse the tree to improve predictions (in case split nodes are used
      # to provide responses)
      try:
          self.stats[y] += w
      except KeyError:
          self.stats[y] = w
  
      old_error = self._mean_error.get()
  
      # Update ADWIN
      self.drift_detector.update(detec_in)
      self._mean_error.update(detec_in)
      error_change = self.drift_detector.drift_detected
  
      # Classification error is decreasing: skip drift adaptation
      if error_change and old_error > self._mean_error.get():
          # Reset the error estimator
          self._mean_error = self._mean_error.clone()
          error_change = False
  
      # Condition to build a new alternate tree
      if error_change:
          # Reset the error estimator
          self._mean_error = self._mean_error.clone()
          self._alternate_tree = tree._new_leaf(parent=self)
          self._alternate_tree.depth -= (
              1  # To ensure we do not skip a tree level
          )
          tree._n_alternate_trees += 1
      # Condition to replace alternate tree
      elif self._alternate_tree:
          alt_n_obs = self._alternate_tree._mean_error.n
          n_obs = self._mean_error.n
          if (
              alt_n_obs > tree.drift_window_threshold
              and n_obs > tree.drift_window_threshold
          ):
              old_error_rate = self._mean_error.get()
              alt_error_rate = self._alternate_tree._mean_error.get()
  
              n = 1.0 / alt_n_obs + 1.0 / n_obs
  
              bound = math.sqrt(
                  2.0
                  * old_error_rate
                  * (1.0 - old_error_rate)
                  * math.log(2.0 / tree.switch_significance)
                  * n
              )
  
              if bound < (old_error_rate - alt_error_rate):
                  tree._n_active_leaves -= self.n_leaves
                  tree._n_active_leaves += self._alternate_tree.n_leaves
                  self.kill_tree_children(tree)
  
                  if parent is not None:
                      parent.children[
                          parent_branch
                      ] = self._alternate_tree
                      self._alternate_tree = None
                  else:
                      # Switch tree root
                      tree._root = tree._root._alternate_tree
                  tree._n_switch_alternate_trees += 1
              elif bound < alt_error_rate - old_error_rate:
                  if isinstance(self._alternate_tree, DTBranch):
                      self._alternate_tree.kill_tree_children(
                          tree
                      )  # noqa
                  self._alternate_tree = None
                  tree._n_pruned_alternate_trees += 1
  
      # Learn one sample in alternate tree and child nodes
      if self._alternate_tree:
          self._alternate_tree.learn_one(
              x,
              y,
              w=w,
              tree=tree,
              parent=parent,
              parent_branch=parent_branch,
          )
  
      try:
          child = self.next(x)
      except KeyError:
          child = None
  
      if child:
          child.learn_one(
              x,
              y,
              w=w,
              tree=tree,
              parent=self,
              parent_branch=self.branch_no(x),
          )
      else:
          # Instance contains a categorical value previously unseen by the split node
          if self.max_branches() == -1 and self.feature in x:  # noqa
              # Creates a new learning node to encompass the new observed feature value
              leaf = tree._new_leaf(parent=self)
              self.add_child(x[self.feature], leaf)  # noqa
              tree._n_active_leaves += 1
              leaf.learn_one(
                  x,
                  y,
                  w=w,
                  tree=tree,
                  parent=self,
                  parent_branch=self.branch_no(x),
              )
          # The split feature is missing in the instance. Hence, we pass the new example
          # to the most traversed path in the current subtree
          else:
              child_id, child = self.most_common_path()
              child.learn_one(
                  x,
                  y,
                  w=w,
                  tree=tree,
                  parent=self,
                  parent_branch=child_id,
              )
  
imports: from __future__ import annotations
  import math
  from river import stats
  from river.utils.norm import normalize_values_in_dict
  from river.utils.random import poisson
  from ..utils import do_naive_bayes_prediction
  from .branch import DTBranch, NominalBinaryBranch, NominalMultiwayBranch, NumericBinaryBranch, NumericMultiwayBranch
  from .htc_nodes import LeafNaiveBayesAdaptive
  from .leaf import HTLeaf
label_desc: Use image node_id 4 for calling the AdaBranchClassifier obj's underlying member method code with example usage: obj.learn_one(x, y) without return types