class_docstr: FIGS (sum of trees) classifier.
  Fast Interpretable Greedy-Tree Sums (FIGS) is an algorithm for fitting concise rule-based models.
  Specifically, FIGS generalizes CART to simultaneously grow a flexible number of trees in a summation.
  The total number of splits across all the trees can be restricted by a pre-specified threshold, keeping the model interpretable.
  Experiments across real-world datasets show that FIGS achieves state-of-the-art prediction performance when restricted to just a few splits (e.g. less than 20).
  https://arxiv.org/abs/2201.11931
class_docstr_tok: ["FIGS","(","sum","of","trees",")","classifier",".","Fast","Interpretable","Greedy-Tree","Sums","(","FIGS",")","is","an","algorithm","for","fitting","concise","rule-based","models",".","Specifically",",","FIGS","generalizes","CART","to","simultaneously","grow","a","flexible","number","of","trees","in","a","summation",".","The","total","number","of","splits","across","all","the","trees","can","be","restricted","by","a","pre-specified","threshold",",","keeping","the","model","interpretable",".","Experiments","across","real-world","datasets","show","that","FIGS","achieves","state-of-the-art","prediction","performance","when","restricted","to","just","a","few","splits","(","e.g",".","less","than","20",")",".","https",":","\/\/arxiv.org\/abs\/2201.11931"]
docstr: Params
  ------
  compare_nodes_with_sample_weight: Deprecated
      If this is set to true and sample_weight is passed, use sample_weight to compare nodes
      Otherwise, use sample_weight only for picking a split given a particular node
docstr_tok: ["Params","--","--","--","compare_nodes_with_sample_weight",":","Deprecated","If","this","is","set","to","true","and","sample_weight","is","passed",",","use","sample_weight","to","compare","nodes","Otherwise",",","use","sample_weight","only","for","picking","a","split","given","a","particular","node"]
code: def _construct_node_with_stump(
      self,
      X,
      y,
      idxs,
      tree_num,
      sample_weight=None,
      compare_nodes_with_sample_weight=True,
      max_features=None,
  ):
      """
      Params
      ------
      compare_nodes_with_sample_weight: Deprecated
          If this is set to true and sample_weight is passed, use sample_weight to compare nodes
          Otherwise, use sample_weight only for picking a split given a particular node
      """
  
      # array indices
      SPLIT = 0
      LEFT = 1
      RIGHT = 2
  
      # fit stump
      stump = tree.DecisionTreeRegressor(
          max_depth=1, max_features=max_features
      )
      sweight = None
      if sample_weight is not None:
          sweight = sample_weight[idxs]
      stump.fit(X[idxs], y[idxs], sample_weight=sweight)
  
      # these are all arrays, arr[0] is split node
      # note: -2 is dummy
      feature = stump.tree_.feature
      threshold = stump.tree_.threshold
  
      impurity = stump.tree_.impurity
      n_node_samples = stump.tree_.n_node_samples
      value = stump.tree_.value
  
      # no split
      if len(feature) == 1:
          # print('no split found!', idxs.sum(), impurity, feature)
          return Node(
              idxs=idxs,
              value=value[SPLIT],
              tree_num=tree_num,
              feature=feature[SPLIT],
              threshold=threshold[SPLIT],
              impurity=impurity[SPLIT],
              impurity_reduction=None,
          )
  
      # manage sample weights
      idxs_split = X[:, feature[SPLIT]] <= threshold[SPLIT]
      idxs_left = idxs_split & idxs
      idxs_right = ~idxs_split & idxs
      if sample_weight is None:
          n_node_samples_left = n_node_samples[LEFT]
          n_node_samples_right = n_node_samples[RIGHT]
      else:
          n_node_samples_left = sample_weight[idxs_left].sum()
          n_node_samples_right = sample_weight[idxs_right].sum()
      n_node_samples_split = n_node_samples_left + n_node_samples_right
  
      # calculate impurity
      impurity_reduction = (
          impurity[SPLIT]
          - impurity[LEFT] * n_node_samples_left / n_node_samples_split
          - impurity[RIGHT]
          * n_node_samples_right
          / n_node_samples_split
      ) * n_node_samples_split
  
      node_split = Node(
          idxs=idxs,
          value=value[SPLIT],
          tree_num=tree_num,
          feature=feature[SPLIT],
          threshold=threshold[SPLIT],
          impurity=impurity[SPLIT],
          impurity_reduction=impurity_reduction,
      )
      # print('\t>>>', node_split, 'impurity', impurity, 'num_pts', idxs.sum(), 'imp_reduc', impurity_reduction)
  
      # manage children
      node_left = Node(
          idxs=idxs_left,
          value=value[LEFT],
          impurity=impurity[LEFT],
          tree_num=tree_num,
      )
      node_right = Node(
          idxs=idxs_right,
          value=value[RIGHT],
          impurity=impurity[RIGHT],
          tree_num=tree_num,
      )
      node_split.setattrs(
          left_temp=node_left,
          right_temp=node_right,
      )
      return node_split
  
imports: from copy import deepcopy
  from typing import List
  import matplotlib.pyplot
  import numpy
  import pandas
  from scipy.special import expit
  from sklearn import datasets
  from sklearn import tree
  from sklearn.base import BaseEstimator, ClassifierMixin, RegressorMixin
  from sklearn.model_selection import train_test_split, cross_val_score
  from sklearn.tree import plot_tree, DecisionTreeClassifier
  from sklearn.utils import check_X_y, check_array
  from sklearn.utils.validation import _check_sample_weight, check_is_fitted
  from imodels.tree.viz_utils import extract_sklearn_tree_from_figs
  from imodels.util.arguments import check_fit_arguments
  from imodels.util.data_util import encode_categories
label_desc: Use image node_id 3 for calling the FIGS obj's underlying member method code with example usage: obj._construct_node_with_stump(X, y, idxs, tree_num, sample_weight, compare_nodes_with_sample_weight, max_features) and returns: node_split, Node