class_docstr: Using tf.gradients to implement the backpropagation was
  inspired by the gradient-based implementation approach proposed by Ancona et al, ICLR 2018. Note
  that this package does not currently use the reveal-cancel rule for ReLu units proposed in DeepLIFT.
class_docstr_tok: ["Using","tf.gradients","to","implement","the","backpropagation","was","inspired","by","the","gradient-based","implementation","approach","proposed","by","Ancona","et","al",",","ICLR","2018",".","Note","that","this","package","does","not","currently","use","the","reveal-cancel","rule","for","ReLu","units","proposed","in","DeepLIFT","."]
docstr: An explainer object for a deep model using a given background dataset.
  
  Note that the complexity of the method scales linearly with the number of background data
  samples. Passing the entire training dataset as `data` will give very accurate expected
  values, but will be computationally expensive. The variance of the expectation estimates scales by
  roughly 1/sqrt(N) for N background data samples. So 100 samples will give a good estimate,
  and 1000 samples a very good estimate of the expected values.
  
  Parameters
  ----------
  model : tf.keras.Model or (input : [tf.Operation], output : tf.Operation)
      A keras model object or a pair of TensorFlow operations (or a list and an op) that
      specifies the input and output of the model to be explained. Note that SHAP values
      are specific to a single output value, so you get an explanation for each element of
      the output tensor (which must be a flat rank one vector).
  
  data : [numpy.array] or [pandas.DataFrame] or function
      The background dataset to use for integrating out features. DeepExplainer integrates
      over all these samples for each explanation. The data passed here must match the input
      operations given to the model. If a function is supplied, it must be a function that
      takes a particular input example and generates the background dataset for that example
  session : None or tensorflow.Session
      The TensorFlow session that has the model we are explaining. If None is passed then
      we do our best to find the right session, first looking for a keras session, then
      falling back to the default TensorFlow session.
  
  learning_phase_flags : None or list of tensors
      If you have your own custom learning phase flags pass them here. When explaining a prediction
      we need to ensure we are not in training mode, since this changes the behavior of ops like
      batch norm or dropout. If None is passed then we look for tensors in the graph that look like
      learning phase flags (this works for Keras models). Note that we assume all the flags should
      have a value of False during predictions (and hence explanations).
docstr_tok: ["An","explainer","object","for","a","deep","model","using","a","given","background","dataset",".","Note","that","the","complexity","of","the","method","scales","linearly","with","the","number","of","background","data","samples",".","Passing","the","entire","training","dataset","as","`","data","`","will","give","very","accurate","expected","values",",","but","will","be","computationally","expensive",".","The","variance","of","the","expectation","estimates","scales","by","roughly","1\/sqrt","(","N",")","for","N","background","data","samples",".","So","100","samples","will","give","a","good","estimate",",","and","1000","samples","a","very","good","estimate","of","the","expected","values",".","Parameters","--","--","--","--","--","model",":","tf.keras.Model","or","(","input",":","[","tf.Operation","]",",","output",":","tf.Operation",")","A","keras","model","object","or","a","pair","of","TensorFlow","operations","(","or","a","list","and","an","op",")","that","specifies","the","input","and","output","of","the","model","to","be","explained",".","Note","that","SHAP","values","are","specific","to","a","single","output","value",",","so","you","get","an","explanation","for","each","element","of","the","output","tensor","(","which","must","be","a","flat","rank","one","vector",")",".","data",":","[","numpy.array","]","or","[","pandas.DataFrame","]","or","function","The","background","dataset","to","use","for","integrating","out","features",".","DeepExplainer","integrates","over","all","these","samples","for","each","explanation",".","The","data","passed","here","must","match","the","input","operations","given","to","the","model",".","If","a","function","is","supplied",",","it","must","be","a","function","that","takes","a","particular","input","example","and","generates","the","background","dataset","for","that","example","session",":","None","or","tensorflow.Session","The","TensorFlow","session","that","has","the","model","we","are","explaining",".","If","None","is","passed","then","we","do","our","best","to","find","the","right","session",",","first","looking","for","a","keras","session",",","then","falling","back","to","the","default","TensorFlow","session",".","learning_phase_flags",":","None","or","list","of","tensors","If","you","have","your","own","custom","learning","phase","flags","pass","them","here",".","When","explaining","a","prediction","we","need","to","ensure","we","are","not","in","training","mode",",","since","this","changes","the","behavior","of","ops","like","batch","norm","or","dropout",".","If","None","is","passed","then","we","look","for","tensors","in","the","graph","that","look","like","learning","phase","flags","(","this","works","for","Keras","models",")",".","Note","that","we","assume","all","the","flags","should","have","a","value","of","False","during","predictions","(","and","hence","explanations",")","."]
code: def __init__(
      self, model, data, session=None, learning_phase_flags=None
  ):
      """An explainer object for a deep model using a given background dataset.
  
      Note that the complexity of the method scales linearly with the number of background data
      samples. Passing the entire training dataset as `data` will give very accurate expected
      values, but will be computationally expensive. The variance of the expectation estimates scales by
      roughly 1/sqrt(N) for N background data samples. So 100 samples will give a good estimate,
      and 1000 samples a very good estimate of the expected values.
  
      Parameters
      ----------
      model : tf.keras.Model or (input : [tf.Operation], output : tf.Operation)
          A keras model object or a pair of TensorFlow operations (or a list and an op) that
          specifies the input and output of the model to be explained. Note that SHAP values
          are specific to a single output value, so you get an explanation for each element of
          the output tensor (which must be a flat rank one vector).
  
      data : [numpy.array] or [pandas.DataFrame] or function
          The background dataset to use for integrating out features. DeepExplainer integrates
          over all these samples for each explanation. The data passed here must match the input
          operations given to the model. If a function is supplied, it must be a function that
          takes a particular input example and generates the background dataset for that example
      session : None or tensorflow.Session
          The TensorFlow session that has the model we are explaining. If None is passed then
          we do our best to find the right session, first looking for a keras session, then
          falling back to the default TensorFlow session.
  
      learning_phase_flags : None or list of tensors
          If you have your own custom learning phase flags pass them here. When explaining a prediction
          we need to ensure we are not in training mode, since this changes the behavior of ops like
          batch norm or dropout. If None is passed then we look for tensors in the graph that look like
          learning phase flags (this works for Keras models). Note that we assume all the flags should
          have a value of False during predictions (and hence explanations).
  
      """
      # try to import tensorflow
      global tf, tf_ops, tf_backprop, tf_execute, tf_gradients_impl
      if tf is None:
          from tensorflow.python.eager import backprop as tf_backprop
          from tensorflow.python.eager import execute as tf_execute
          from tensorflow.python.framework import (
              ops as tf_ops,
          )
          from tensorflow.python.ops import (
              gradients_impl as tf_gradients_impl,
          )
  
          if not hasattr(tf_gradients_impl, "_IsBackpropagatable"):
              from tensorflow.python.ops import (
                  gradients_util as tf_gradients_impl,
              )
          import tensorflow as tf
  
          if version.parse(tf.__version__) < version.parse("1.4.0"):
              warnings.warn(
                  "Your TensorFlow version is older than 1.4.0 and not supported."
              )
  
      if version.parse(tf.__version__) >= version.parse("2.4.0"):
          warnings.warn(
              "Your TensorFlow version is newer than 2.4.0 and so graph support has been removed in eager mode and some static graphs may not be supported. See PR #1483 for discussion."
          )
  
      # determine the model inputs and outputs
      self.model_inputs = _get_model_inputs(model)
      self.model_output = _get_model_output(model)
      assert not isinstance(
          self.model_output, list
      ), "The model output to be explained must be a single tensor!"
      assert (
          len(self.model_output.shape) < 3
      ), "The model output must be a vector or a single value!"
      self.multi_output = True
      if len(self.model_output.shape) == 1:
          self.multi_output = False
  
      if tf.executing_eagerly():
          if isinstance(model, tuple) or isinstance(model, list):
              assert (
                  len(model) == 2
              ), "When a tuple is passed it must be of the form (inputs, outputs)"
              from tensorflow.keras import Model
  
              self.model = Model(model[0], model[1])
          else:
              self.model = model
  
      # check if we have multiple inputs
      self.multi_input = True
      if (
          not isinstance(self.model_inputs, list)
          or len(self.model_inputs) == 1
      ):
          self.multi_input = False
          if not isinstance(self.model_inputs, list):
              self.model_inputs = [self.model_inputs]
      if not isinstance(data, list) and (
          hasattr(data, "__call__") is False
      ):
          data = [data]
      self.data = data
  
      self._vinputs = (
          {}
      )  # used to track what op inputs depends on the model inputs
      self.orig_grads = {}
  
      if not tf.executing_eagerly():
          self.session = _get_session(session)
  
      self.graph = _get_graph(self)
  
      # if no learning phase flags were given we go looking for them
      # ...this will catch the one that keras uses
      # we need to find them since we want to make sure learning phase flags are set to False
      if learning_phase_flags is None:
          self.learning_phase_ops = []
          for op in self.graph.get_operations():
              if (
                  "learning_phase" in op.name
                  and op.type == "Const"
                  and len(op.outputs[0].shape) == 0
              ):
                  if op.outputs[0].dtype == tf.bool:
                      self.learning_phase_ops.append(op)
          self.learning_phase_flags = [
              op.outputs[0] for op in self.learning_phase_ops
          ]
      else:
          self.learning_phase_ops = [t.op for t in learning_phase_flags]
  
      # save the expected output of the model
      # if self.data is a function, set self.expected_value to None
      if hasattr(self.data, "__call__"):
          self.expected_value = None
      else:
          if self.data[0].shape[0] > 5000:
              warnings.warn(
                  "You have provided over 5k background samples! For better performance consider using smaller random sample."
              )
          if not tf.executing_eagerly():
              self.expected_value = self.run(
                  self.model_output, self.model_inputs, self.data
              ).mean(0)
          else:
              # if type(self.model)is tuple:
              #    self.fModel(cnn.inputs, cnn.get_layer(theNameYouWant).outputs)
              self.expected_value = tf.reduce_mean(
                  self.model(self.data), 0
              )
  
      if not tf.executing_eagerly():
          self._init_between_tensors(
              self.model_output.op, self.model_inputs
          )
  
      # make a blank array that will get lazily filled in with the SHAP value computation
      # graphs for each output. Lazy is important since if there are 1000 outputs and we
      # only explain the top 5 it would be a waste to build graphs for the other 995
      if not self.multi_output:
          self.phi_symbolics = [None]
      else:
          noutputs = self.model_output.shape.as_list()[1]
          if noutputs is not None:
              self.phi_symbolics = [None for i in range(noutputs)]
          else:
              raise DimensionError(
                  "The model output tensor to be explained cannot have a static shape in dim 1 of None!"
              )
  
imports: import warnings
  import numpy
  from packaging import version
  from ...utils._exceptions import DimensionError
  from .._explainer import Explainer
  from ..tf_utils import _get_graph, _get_model_inputs, _get_model_output, _get_session
  from .deep_utils import _check_additivity
label_desc: Use image node_id 1 to create a new TFDeep object from inherited base classes: Explainer with example: obj = TFDeep(model, data, session, learning_phase_flags)