class_docstr: Uses Tree SHAP algorithms to explain the output of ensemble tree models.
  
  Tree SHAP is a fast and exact method to estimate SHAP values for tree models and ensembles of trees,
  under several different possible assumptions about feature dependence. It depends on fast C++
  implementations either inside an external model package or in the local compiled C extension.
class_docstr_tok: ["Uses","Tree","SHAP","algorithms","to","explain","the","output","of","ensemble","tree","models",".","Tree","SHAP","is","a","fast","and","exact","method","to","estimate","SHAP","values","for","tree","models","and","ensembles","of","trees",",","under","several","different","possible","assumptions","about","feature","dependence",".","It","depends","on","fast","C++","implementations","either","inside","an","external","model","package","or","in","the","local","compiled","C","extension","."]
docstr: Estimate the SHAP values for a set of samples.
  
  Parameters
  ----------
  X : numpy.array, pandas.DataFrame or catboost.Pool (for catboost)
      A matrix of samples (# samples x # features) on which to explain the model's output.
  
  y : numpy.array
      An array of label values for each sample. Used when explaining loss functions.
  
  tree_limit : None (default) or int
      Limit the number of trees used by the model. By default, the limit of the original model
      is used (``None``). ``-1`` means no limit.
  
  approximate : bool
      Run fast, but only roughly approximate the Tree SHAP values. This runs a method
      previously proposed by Saabas which only considers a single feature ordering. Take care
      since this does not have the consistency guarantees of Shapley values and places too
      much weight on lower splits in the tree.
  
  check_additivity : bool
      Run a validation check that the sum of the SHAP values equals the output of the model. This
      check takes only a small amount of time, and will catch potential unforeseen errors.
      Note that this check only runs right now when explaining the margin of the model.
  
  Returns
  -------
  array or list
      For models with a single output, this returns a matrix of SHAP values
      (# samples x # features). Each row sums to the difference between the model output for that
      sample and the expected value of the model output (which is stored in the ``expected_value``
      attribute of the explainer when it is constant). For models with vector outputs, this returns
      a list of such matrices, one for each output.
docstr_tok: ["Estimate","the","SHAP","values","for","a","set","of","samples",".","Parameters","--","--","--","--","--","X",":","numpy.array",",","pandas.DataFrame","or","catboost.Pool","(","for","catboost",")","A","matrix","of","samples","(","#","samples","x","#","features",")","on","which","to","explain","the","model","'s","output",".","y",":","numpy.array","An","array","of","label","values","for","each","sample",".","Used","when","explaining","loss","functions",".","tree_limit",":","None","(","default",")","or","int","Limit","the","number","of","trees","used","by","the","model",".","By","default",",","the","limit","of","the","original","model","is","used","(","``","None","``",")",".","``","-1","``","means","no","limit",".","approximate",":","bool","Run","fast",",","but","only","roughly","approximate","the","Tree","SHAP","values",".","This","runs","a","method","previously","proposed","by","Saabas","which","only","considers","a","single","feature","ordering",".","Take","care","since","this","does","not","have","the","consistency","guarantees","of","Shapley","values","and","places","too","much","weight","on","lower","splits","in","the","tree",".","check_additivity",":","bool","Run","a","validation","check","that","the","sum","of","the","SHAP","values","equals","the","output","of","the","model",".","This","check","takes","only","a","small","amount","of","time",",","and","will","catch","potential","unforeseen","errors",".","Note","that","this","check","only","runs","right","now","when","explaining","the","margin","of","the","model",".","Returns","--","--","--","-","array","or","list","For","models","with","a","single","output",",","this","returns","a","matrix","of","SHAP","values","(","#","samples","x","#","features",")",".","Each","row","sums","to","the","difference","between","the","model","output","for","that","sample","and","the","expected","value","of","the","model","output","(","which","is","stored","in","the","``","expected_value","``","attribute","of","the","explainer","when","it","is","constant",")",".","For","models","with","vector","outputs",",","this","returns","a","list","of","such","matrices",",","one","for","each","output","."]
code: def shap_values(
      self,
      X,
      y=None,
      tree_limit=None,
      approximate=False,
      check_additivity=True,
      from_call=False,
  ):
      """Estimate the SHAP values for a set of samples.
  
      Parameters
      ----------
      X : numpy.array, pandas.DataFrame or catboost.Pool (for catboost)
          A matrix of samples (# samples x # features) on which to explain the model's output.
  
      y : numpy.array
          An array of label values for each sample. Used when explaining loss functions.
  
      tree_limit : None (default) or int
          Limit the number of trees used by the model. By default, the limit of the original model
          is used (``None``). ``-1`` means no limit.
  
      approximate : bool
          Run fast, but only roughly approximate the Tree SHAP values. This runs a method
          previously proposed by Saabas which only considers a single feature ordering. Take care
          since this does not have the consistency guarantees of Shapley values and places too
          much weight on lower splits in the tree.
  
      check_additivity : bool
          Run a validation check that the sum of the SHAP values equals the output of the model. This
          check takes only a small amount of time, and will catch potential unforeseen errors.
          Note that this check only runs right now when explaining the margin of the model.
  
      Returns
      -------
      array or list
          For models with a single output, this returns a matrix of SHAP values
          (# samples x # features). Each row sums to the difference between the model output for that
          sample and the expected value of the model output (which is stored in the ``expected_value``
          attribute of the explainer when it is constant). For models with vector outputs, this returns
          a list of such matrices, one for each output.
      """
      # see if we have a default tree_limit in place.
      if tree_limit is None:
          tree_limit = (
              -1
              if self.model.tree_limit is None
              else self.model.tree_limit
          )
  
      # shortcut using the C++ version of Tree SHAP in XGBoost, LightGBM, and CatBoost
      if (
          self.feature_perturbation == "tree_path_dependent"
          and self.model.model_type != "internal"
          and self.data is None
      ):
          model_output_vals = None
          phi = None
          if self.model.model_type == "xgboost":
              import xgboost
  
              if not isinstance(X, xgboost.core.DMatrix):
                  # Retrieve any DMatrix properties if they have been set on the TreeEnsemble Class
                  dmatrix_props = getattr(
                      self.model, "_xgb_dmatrix_props", {}
                  )
                  X = xgboost.DMatrix(X, **dmatrix_props)
              if tree_limit == -1:
                  tree_limit = 0
              try:
                  phi = self.model.original_model.predict(
                      X,
                      iteration_range=(0, tree_limit),
                      pred_contribs=True,
                      approx_contribs=approximate,
                      validate_features=False,
                  )
              except ValueError as e:
                  emsg = (
                      "This reshape error is often caused by passing a bad data matrix to SHAP. "
                      "See https://github.com/shap/shap/issues/580."
                  )
                  raise ValueError(emsg) from e
  
              if check_additivity and self.model.model_output == "raw":
                  xgb_tree_limit = (
                      tree_limit // self.model.num_stacked_models
                  )
                  model_output_vals = self.model.original_model.predict(
                      X,
                      iteration_range=(0, xgb_tree_limit),
                      output_margin=True,
                      validate_features=False,
                  )
  
          elif self.model.model_type == "lightgbm":
              assert (
                  not approximate
              ), "approximate=True is not supported for LightGBM models!"
              phi = self.model.original_model.predict(
                  X, num_iteration=tree_limit, pred_contrib=True
              )
              # Note: the data must be joined on the last axis
              if (
                  self.model.original_model.params["objective"]
                  == "binary"
              ):
                  if not from_call:
                      warnings.warn(
                          "LightGBM binary classifier with TreeExplainer shap values output has changed to a list of ndarray"
                      )
                  phi = np.concatenate((0 - phi, phi), axis=-1)
              if phi.shape[1] != X.shape[1] + 1:
                  try:
                      phi = phi.reshape(
                          X.shape[0],
                          phi.shape[1] // (X.shape[1] + 1),
                          X.shape[1] + 1,
                      )
                  except ValueError as e:
                      emsg = (
                          "This reshape error is often caused by passing a bad data matrix to SHAP. "
                          "See https://github.com/shap/shap/issues/580."
                      )
                      raise ValueError(emsg) from e
  
          elif (
              self.model.model_type == "catboost"
          ):  # thanks to the CatBoost team for implementing this...
              assert (
                  not approximate
              ), "approximate=True is not supported for CatBoost models!"
              assert (
                  tree_limit == -1
              ), "tree_limit is not yet supported for CatBoost models!"
              import catboost
  
              if type(X) != catboost.Pool:
                  X = catboost.Pool(
                      X, cat_features=self.model.cat_feature_indices
                  )
              phi = self.model.original_model.get_feature_importance(
                  data=X, fstr_type="ShapValues"
              )
  
          # note we pull off the last column and keep it as our expected_value
          if phi is not None:
              if len(phi.shape) == 3:
                  self.expected_value = [
                      phi[0, i, -1] for i in range(phi.shape[1])
                  ]
                  out = [phi[:, i, :-1] for i in range(phi.shape[1])]
              else:
                  self.expected_value = phi[0, -1]
                  out = phi[:, :-1]
  
              if check_additivity and model_output_vals is not None:
                  self.assert_additivity(out, model_output_vals)
  
              return out
  
      (
          X,
          y,
          X_missing,
          flat_output,
          tree_limit,
          check_additivity,
      ) = self._validate_inputs(X, y, tree_limit, check_additivity)
      transform = self.model.get_transform()
  
      # run the core algorithm using the C extension
      assert_import("cext")
      phi = np.zeros(
          (X.shape[0], X.shape[1] + 1, self.model.num_outputs)
      )
      if not approximate:
          _cext.dense_tree_shap(
              self.model.children_left,
              self.model.children_right,
              self.model.children_default,
              self.model.features,
              self.model.thresholds,
              self.model.values,
              self.model.node_sample_weight,
              self.model.max_depth,
              X,
              X_missing,
              y,
              self.data,
              self.data_missing,
              tree_limit,
              self.model.base_offset,
              phi,
              feature_perturbation_codes[self.feature_perturbation],
              output_transform_codes[transform],
              False,
          )
      else:
          _cext.dense_tree_saabas(
              self.model.children_left,
              self.model.children_right,
              self.model.children_default,
              self.model.features,
              self.model.thresholds,
              self.model.values,
              self.model.max_depth,
              tree_limit,
              self.model.base_offset,
              output_transform_codes[transform],
              X,
              X_missing,
              y,
              phi,
          )
  
      out = self._get_shap_output(phi, flat_output)
      if check_additivity and self.model.model_output == "raw":
          self.assert_additivity(out, self.model.predict(X))
  
      return out
  
imports: import json
  import os
  import struct
  import time
  import warnings
  import numpy
  import pandas
  import scipy.sparse
  import scipy.special
  from packaging import version
  from ..None import maskers
  from .._explanation import Explanation
  from ..utils import assert_import, record_import_error, safe_isinstance
  from ..utils._exceptions import DimensionError, ExplainerError, InvalidFeaturePerturbationError, InvalidMaskerError, InvalidModelError
  from ..utils._legacy import DenseData
  from ._explainer import Explainer
label_desc: Use image node_id 5 for calling the TreeExplainer obj's underlying member method code with example usage: obj.shap_values(X, y, tree_limit, approximate, check_additivity, from_call) and returns: out, out