class_docstr: Uses Shapley values to explain any machine learning model or python function.
  
  This is the primary explainer interface for the SHAP library. It takes any combination
  of a model and masker and returns a callable subclass object that implements
  the particular estimation algorithm that was chosen.
docstr: Explains the output of model(*args), where args is a list of parallel iterable datasets.
  
  Note this default version could be an abstract method that is implemented by each algorithm-specific
  subclass of Explainer. Descriptions of each subclasses' __call__ arguments
  are available in their respective doc-strings.
docstr_tok: ["Explains","the","output","of","model","(","*","args",")",",","where","args","is","a","list","of","parallel","iterable","datasets",".","Note","this","default","version","could","be","an","abstract","method","that","is","implemented","by","each","algorithm-specific","subclass","of","Explainer",".","Descriptions","of","each","subclasses","'","__call__","arguments","are","available","in","their","respective","doc-strings","."]
code: def __call__(
      self,
      *args,
      max_evals="auto",
      main_effects=False,
      error_bounds=False,
      batch_size="auto",
      outputs=None,
      silent=False,
      **kwargs,
  ):
      """Explains the output of model(*args), where args is a list of parallel iterable datasets.
  
      Note this default version could be an abstract method that is implemented by each algorithm-specific
      subclass of Explainer. Descriptions of each subclasses' __call__ arguments
      are available in their respective doc-strings.
      """
  
      # if max_evals == "auto":
      #     self._brute_force_fallback
  
      start_time = time.time()
  
      if (
          issubclass(type(self.masker), maskers.OutputComposite)
          and len(args) == 2
      ):
          self.masker.model = models.TextGeneration(
              target_sentences=args[1]
          )
          args = args[:1]
      # parse our incoming arguments
      num_rows = None
      args = list(args)
      if self.feature_names is None:
          feature_names = [None for _ in range(len(args))]
      elif issubclass(type(self.feature_names[0]), (list, tuple)):
          feature_names = copy.deepcopy(self.feature_names)
      else:
          feature_names = [copy.deepcopy(self.feature_names)]
      for i in range(len(args)):
          # try and see if we can get a length from any of the for our progress bar
          if num_rows is None:
              try:
                  num_rows = len(args[i])
              except Exception:
                  pass
  
          # convert DataFrames to numpy arrays
          if isinstance(args[i], pd.DataFrame):
              feature_names[i] = list(args[i].columns)
              args[i] = args[i].to_numpy()
  
          # convert nlp Dataset objects to lists
          if safe_isinstance(args[i], "nlp.arrow_dataset.Dataset"):
              args[i] = args[i]["text"]
          elif issubclass(type(args[i]), dict) and "text" in args[i]:
              args[i] = args[i]["text"]
  
      if batch_size == "auto":
          if hasattr(self.masker, "default_batch_size"):
              batch_size = self.masker.default_batch_size
          else:
              batch_size = 10
  
      # loop over each sample, filling in the values array
      values = []
      output_indices = []
      expected_values = []
      mask_shapes = []
      main_effects = []
      hierarchical_values = []
      clustering = []
      output_names = []
      error_std = []
      if callable(getattr(self.masker, "feature_names", None)):
          feature_names = [[] for _ in range(len(args))]
      for row_args in show_progress(
          zip(*args),
          num_rows,
          self.__class__.__name__ + " explainer",
          silent,
      ):
          row_result = self.explain_row(
              *row_args,
              max_evals=max_evals,
              main_effects=main_effects,
              error_bounds=error_bounds,
              batch_size=batch_size,
              outputs=outputs,
              silent=silent,
              **kwargs,
          )
          values.append(row_result.get("values", None))
          output_indices.append(row_result.get("output_indices", None))
          expected_values.append(
              row_result.get("expected_values", None)
          )
          mask_shapes.append(row_result["mask_shapes"])
          main_effects.append(row_result.get("main_effects", None))
          clustering.append(row_result.get("clustering", None))
          hierarchical_values.append(
              row_result.get("hierarchical_values", None)
          )
          tmp = row_result.get("output_names", None)
          output_names.append(tmp(*row_args) if callable(tmp) else tmp)
          error_std.append(row_result.get("error_std", None))
          if callable(getattr(self.masker, "feature_names", None)):
              row_feature_names = self.masker.feature_names(*row_args)
              for i in range(len(row_args)):
                  feature_names[i].append(row_feature_names[i])
  
      # split the values up according to each input
      arg_values = [[] for a in args]
      for i, v in enumerate(values):
          pos = 0
          for j in range(len(args)):
              mask_length = np.prod(mask_shapes[i][j])
              arg_values[j].append(values[i][pos : pos + mask_length])
              pos += mask_length
  
      # collapse the arrays as possible
      expected_values = pack_values(expected_values)
      main_effects = pack_values(main_effects)
      output_indices = pack_values(output_indices)
      main_effects = pack_values(main_effects)
      hierarchical_values = pack_values(hierarchical_values)
      error_std = pack_values(error_std)
      clustering = pack_values(clustering)
  
      # getting output labels
      ragged_outputs = False
      if output_indices is not None:
          ragged_outputs = not all(
              len(x) == len(output_indices[0]) for x in output_indices
          )
      if self.output_names is None:
          if None not in output_names:
              if not ragged_outputs:
                  sliced_labels = np.array(output_names)
              else:
                  sliced_labels = [
                      np.array(output_names[i])[index_list]
                      for i, index_list in enumerate(output_indices)
                  ]
          else:
              sliced_labels = None
      else:
          assert (
              output_indices is not None
          ), "You have passed a list for output_names but the model seems to not have multiple outputs!"
          labels = np.array(self.output_names)
          sliced_labels = [
              labels[index_list] for index_list in output_indices
          ]
          if not ragged_outputs:
              sliced_labels = np.array(sliced_labels)
  
      if (
          isinstance(sliced_labels, np.ndarray)
          and len(sliced_labels.shape) == 2
      ):
          if np.all(sliced_labels[0, :] == sliced_labels):
              sliced_labels = sliced_labels[0]
  
      # allow the masker to transform the input data to better match the masking pattern
      # (such as breaking text into token segments)
      if hasattr(self.masker, "data_transform"):
          new_args = []
          for row_args in zip(*args):
              new_args.append(
                  [
                      pack_values(v)
                      for v in self.masker.data_transform(*row_args)
                  ]
              )
          args = list(zip(*new_args))
  
      # build the explanation objects
      out = []
      for j, data in enumerate(args):
          # reshape the attribution values using the mask_shapes
          tmp = []
          for i, v in enumerate(arg_values[j]):
              if np.prod(mask_shapes[i][j]) != np.prod(
                  v.shape
              ):  # see if we have multiple outputs
                  tmp.append(v.reshape(*mask_shapes[i][j], -1))
              else:
                  tmp.append(v.reshape(*mask_shapes[i][j]))
          arg_values[j] = pack_values(tmp)
  
          if feature_names[j] is None:
              feature_names[j] = [
                  "Feature " + str(i) for i in range(data.shape[1])
              ]
  
          # build an explanation object for this input argument
          out.append(
              Explanation(
                  arg_values[j],
                  expected_values,
                  data,
                  feature_names=feature_names[j],
                  main_effects=main_effects,
                  clustering=clustering,
                  hierarchical_values=hierarchical_values,
                  output_names=sliced_labels,  # self.output_names
                  error_std=error_std,
                  compute_time=time.time() - start_time
                  # output_shape=output_shape,
                  # lower_bounds=v_min, upper_bounds=v_max
              )
          )
      return out[0] if len(out) == 1 else out
  
imports: import copy
  import time
  import numpy
  import pandas
  import scipy.sparse
  from ..None import explainers, links, maskers, models
  from .._explanation import Explanation
  from .._serializable import Deserializer, Serializable, Serializer
  from ..maskers import Masker
  from ..models import Model
  from ..utils import safe_isinstance, show_progress
  from ..utils._exceptions import InvalidAlgorithmError
  from ..utils.transformers import is_transformers_lm
label_desc: Use image node_id 2 for calling the Explainer obj's underlying member method code with example usage: obj.__call__() and returns: unknown