docstr: Shrink the tree
docstr_tok: ["Shrink","the","tree"]
code: def _shrink_tree(
      self,
      tree,
      reg_param,
      i=0,
      parent_val=None,
      parent_num=None,
      cum_sum=0,
  ):
      """Shrink the tree"""
      if reg_param is None:
          reg_param = 1.0
      left = tree.children_left[i]
      right = tree.children_right[i]
      is_leaf = left == right
      n_samples = tree.weighted_n_node_samples[i]
      if isinstance(self, RegressorMixin) or isinstance(
          self.estimator_, GradientBoostingClassifier
      ):
          val = deepcopy(tree.value[i, :, :])
      else:  # If classification, normalize to probability vector
          val = tree.value[i, :, :] / n_samples
  
      # Step 1: Update cum_sum
      # if root
      if parent_val is None and parent_num is None:
          cum_sum = val
  
      # if has parent
      else:
          if self.shrinkage_scheme_ == "node_based":
              val_new = (val - parent_val) / (
                  1 + reg_param / parent_num
              )
          elif self.shrinkage_scheme_ == "constant":
              val_new = (val - parent_val) / (1 + reg_param)
          else:  # leaf_based
              val_new = 0
          cum_sum += val_new
  
      # Step 2: Update node values
      if (
          self.shrinkage_scheme_ == "node_based"
          or self.shrinkage_scheme_ == "constant"
      ):
          tree.value[i, :, :] = cum_sum
      else:  # leaf_based
          if is_leaf:  # update node values if leaf_based
              root_val = tree.value[0, :, :]
              tree.value[i, :, :] = root_val + (val - root_val) / (
                  1 + reg_param / n_samples
              )
          else:
              tree.value[i, :, :] = val
  
              # Step 3: Recurse if not leaf
      if not is_leaf:
          self._shrink_tree(
              tree,
              reg_param,
              left,
              parent_val=val,
              parent_num=n_samples,
              cum_sum=deepcopy(cum_sum),
          )
          self._shrink_tree(
              tree,
              reg_param,
              right,
              parent_val=val,
              parent_num=n_samples,
              cum_sum=deepcopy(cum_sum),
          )
  
          # edit the non-leaf nodes for later visualization (doesn't effect predictions)
  
      return tree
  
imports: import time
  from copy import deepcopy
  from typing import List
  import numpy
  from sklearn import datasets
  from sklearn.base import BaseEstimator, RegressorMixin, ClassifierMixin
  from sklearn.metrics import r2_score, mean_squared_error, log_loss
  from sklearn.model_selection import cross_val_score, KFold
  from sklearn.model_selection import train_test_split
  from sklearn.tree import DecisionTreeRegressor, DecisionTreeClassifier, export_text
  from sklearn.ensemble import GradientBoostingClassifier, GradientBoostingRegressor, RandomForestRegressor
  from imodels.util import checks
  from imodels.util.arguments import check_fit_arguments
  from imodels.util.tree import compute_tree_complexity
label_desc: Use image node_id 4 for calling the HSTree obj's underlying member method code with example usage: obj._shrink_tree(tree, reg_param, i, parent_val, parent_num, cum_sum) and returns: tree