shap / shap

A game theoretic approach to explain the output of any machine learning model.
https://shap.readthedocs.io
MIT License
22.11k stars 3.22k forks source link

AttributeError: 'KerasTensor' object has no attribute 'graph' #1694

Open imrankhan441 opened 3 years ago

imrankhan441 commented 3 years ago

Code

!pip install -U tensorflow
!pip install -U keras
!pip install -U shap

# This model training code is directly from:
# https://github.com/keras-team/keras/blob/master/examples/imdb_lstm.py

'''Trains an LSTM model on the IMDB sentiment classification task.
The dataset is actually too small for LSTM to be of any advantage
compared to simpler, much faster methods such as TF-IDF + LogReg.
# Notes
- RNNs are tricky. Choice of batch size is important,
choice of loss and optimizer is critical, etc.
Some configurations won't converge.
- LSTM loss decrease patterns during training can be quite different
from what you see with CNNs/MLPs/etc.
'''
from __future__ import print_function

from keras.preprocessing import sequence
from keras.models import Sequential
from keras.layers import Dense, Embedding
from keras.layers import LSTM
from keras.datasets import imdb

max_features = 20000
maxlen = 80  # cut texts after this number of words (among top max_features most common words)
batch_size = 32

print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')

print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)

print('Build model...')
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))

# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

print('Train...')
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=15,
          validation_data=(x_test, y_test))
score, acc = model.evaluate(x_test, y_test,
                            batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)

import shap

# we use the first 100 training examples as our background dataset to integrate over
explainer = shap.DeepExplainer(model, x_train[:100])

# explain the first 10 predictions
# explaining each prediction requires 2 * background dataset size runs
shap_values = explainer.shap_values(x_test[:10])

# init the JS visualization code
shap.initjs()

# transform the indexes to words
import numpy as np
words = imdb.get_word_index()
num2word = {}
for w in words.keys():
    num2word[words[w]] = w
x_test_words = np.stack([np.array(list(map(lambda x: num2word.get(x, "NONE"), x_test[i]))) for i in range(10)])

# plot the explanation of the first prediction
# Note the model is "multi-output" because it is rank-2 but only has one column
shap.force_plot(explainer.expected_value[0], shap_values[0][0], x_test_words[0])

Error

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-13-d0b49e7ececc> in <module>
      2 
      3 # we use the first 100 training examples as our background dataset to integrate over
----> 4 explainer = shap.DeepExplainer(model, x_train[:100])
      5 
      6 # explain the first 10 predictions

/srv/conda/envs/notebook/lib/python3.7/site-packages/shap/explainers/_deep/__init__.py in __init__(self, model, data, session, learning_phase_flags)
     82 
     83         if framework == 'tensorflow':
---> 84             self.explainer = TFDeep(model, data, session, learning_phase_flags)
     85         elif framework == 'pytorch':
     86             self.explainer = PyTorchDeep(model, data)

/srv/conda/envs/notebook/lib/python3.7/site-packages/shap/explainers/_deep/deep_tf.py in __init__(self, model, data, session, learning_phase_flags)
    129             self.session = _get_session(session)
    130 
--> 131         self.graph = _get_graph(self)
    132 
    133         # if no learning phase flags were given we go looking for them

/srv/conda/envs/notebook/lib/python3.7/site-packages/shap/explainers/tf_utils.py in _get_graph(explainer)
     44         return explainer.session.graph
     45     else:
---> 46         return explainer.model_output.graph
     47 
     48 def _get_model_inputs(model):

AttributeError: 'KerasTensor' object has no attribute 'graph'

Please Fix this as soon as possible

janesser commented 3 years ago

same here; persuminly looks like a tf2 induced issue where adopting tf.compat.v1 would help.

https://github.com/slundberg/shap/blob/40478171b90faf2d5c1d61a000a6cbcb01a81101/shap/explainers/_deep/deep_tf.py#L95

here is the preceeding discussion: https://github.com/slundberg/shap/pull/1483

imrankhan441 commented 3 years ago

do have any idea what can I do now.

janesser commented 3 years ago

i tried

!pip install git+https://github.com/Zahlii/shap.git

import tensorflow as tf
tf.compat.v1.disable_eager_execution()

but came to some:

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-16-0a78ed66fc25> in <module>
     32         )]
     33     )
---> 34     shap_values = exp(X_test)
     35     shap.plots.heatmap(shap_values)
     36 #

/opt/conda/lib/python3.7/site-packages/shap/explainers/_explainer.py in __call__(self, max_evals, main_effects, error_bounds, batch_size, outputs, silent, *args, **kwargs)
    168         num_rows = None
    169         args = list(args)
--> 170         if self.feature_names is None:
    171             feature_names = [None for _ in range(len(args))]
    172         elif issubclass(type(self.feature_names[0]), (list, tuple)):

AttributeError: 'Deep' object has no attribute 'feature_names'
Crispyjones7387 commented 3 years ago

I'm also running into the same issue.

---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
<ipython-input-19-ef2d2c897d75> in <module>()
      4 
      5 # explain predictions of the model on three images
----> 6 e = shap.DeepExplainer(model, background)
      7 # ...or pass tensors directly
      8 # e = shap.DeepExplainer((model.layers[0].input, model.layers[-1].output), background)

2 frames
/usr/local/lib/python3.6/dist-packages/shap/explainers/tf_utils.py in _get_graph(explainer)
     44         return explainer.session.graph
     45     else:
---> 46         return explainer.model_output.graph
     47 
     48 def _get_model_inputs(model):

AttributeError: 'KerasTensor' object has no attribute 'graph'

I am using tf.Keras but the issue still continues to persist.

Arnab9Codes commented 3 years ago

Same issue. Is there a way around?

`AttributeError Traceback (most recent call last)

in () ----> 1 explainer=shap.DeepExplainer(model,trainX) 2 frames /usr/local/lib/python3.6/dist-packages/shap/explainers/tf_utils.py in _get_graph(explainer) 44 return explainer.session.graph 45 else: ---> 46 return explainer.model_output.graph 47 48 def _get_model_inputs(model): AttributeError: 'KerasTensor' object has no attribute 'graph'`
roma-glushko commented 3 years ago

+1 Keras model was created via Functional API, but the error is the same: https://github.com/roma-glushko/kaggle-digit-recognizer/blob/master/index.ipynb

tonydisera commented 3 years ago

I am seeing the same issue.

Arnab9Codes commented 3 years ago

Somebody in another issue suggested to use tensorflow 1.15 that removes this particular issue,

evroscchristodoulou commented 3 years ago

Hi guys any updates ? I have the same issue

imrankhan441 commented 3 years ago

If anyone has an emergency, use this solution. Hope it's work.

!pip install git+https://github.com/Zahlii/shap.git

import tensorflow as tf
from __future__ import print_function

from tensorflow.keras.preprocessing import sequence
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense, Embedding
from tensorflow.keras.layers import LSTM
from tensorflow.keras.datasets import imdb

tf.compat.v1.disable_v2_behavior()

max_features = 20000
maxlen = 80  # cut texts after this number of words (among top max_features most common words)
batch_size = 32

print('Loading data...')
(x_train, y_train), (x_test, y_test) = imdb.load_data(num_words=max_features)
print(len(x_train), 'train sequences')
print(len(x_test), 'test sequences')

print('Pad sequences (samples x time)')
x_train = sequence.pad_sequences(x_train, maxlen=maxlen)
x_test = sequence.pad_sequences(x_test, maxlen=maxlen)
print('x_train shape:', x_train.shape)
print('x_test shape:', x_test.shape)

print('Build model...')
model = Sequential()
model.add(Embedding(max_features, 128))
model.add(LSTM(128, dropout=0.2, recurrent_dropout=0.2))
model.add(Dense(1, activation='sigmoid'))

# try using different optimizers and different optimizer configs
model.compile(loss='binary_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

print('Train...')
model.fit(x_train, y_train,
          batch_size=batch_size,
          epochs=15,
          validation_data=(x_test, y_test))
score, acc = model.evaluate(x_test, y_test,
                            batch_size=batch_size)
print('Test score:', score)
print('Test accuracy:', acc)

import shap

# we use the first 100 training examples as our background dataset to integrate over
explainer = shap.DeepExplainer(model, x_train[:100])

# explain the first 10 predictions
# explaining each prediction requires 2 * background dataset size runs
shap_values = explainer.shap_values(x_test[:10])

# init the JS visualization code
shap.initjs()

# transform the indexes to words
import numpy as np
words = imdb.get_word_index()
num2word = {}
for w in words.keys():
    num2word[words[w]] = w
x_test_words = np.stack([np.array(list(map(lambda x: num2word.get(x, "NONE"), x_test[i]))) for i in range(10)])

# plot the explanation of the first prediction
# Note the model is "multi-output" because it is rank-2 but only has one column
shap.force_plot(explainer.expected_value[0], shap_values[0][0], x_test_words[0])
tazitoo commented 3 years ago

Same issue, error while training DeepExplainer on tf.keras functional model:
AttributeError: 'KerasTensor' object has no attribute 'graph'
Adding these two lines to my script fixed it for me: import tensorflow as tf
tf.compat.v1.disable_v2_behavior()

No need to install alternative versions from other repos.

Griefberg commented 3 years ago

any news on that except using tf.compat.v1.disable_v2_behavior() which is not ideal in any sense?

k-andriani commented 3 years ago

Hi guys, i installed matplotlib and worked for me. pip install matplotlib

janesser commented 3 years ago

You may also be interested in the solution proposed here #1483, though i don't know if it will be integrated.

csvankhede commented 3 years ago

I had the same issue, it worked with tensorflow version 2.2.0

ratmcu commented 3 years ago

Same issue, error while training DeepExplainer on tf.keras functional model: AttributeError: 'KerasTensor' object has no attribute 'graph' Adding these two lines to my script fixed it for me: import tensorflow as tf tf.compat.v1.disable_v2_behavior()

No need to install alternative versions from other repos.

this worked for me, thanks tf version == 2.4.1

janesser commented 3 years ago

@ratmcu did you try 0.38.1 resulting from above PR already? i suppose there is plenty of "good" v2 behaviour you want to keep activated.

ratmcu commented 3 years ago

@ratmcu did you try 0.38.1 resulting from above PR already? i suppose there is plenty of "good" v2 behaviour you want to keep activated.

@janesser it is already 0.38.1

janesser commented 3 years ago

accept my apologies, i meant 0.38.2 which contains above PR, which isn't released yet.

@slundberg could you please release it.

@ratmcu check this one https://www.kaggle.com/janesser777/tf2-visualizing-fit re-run it this morning and it still works fine with DeepExplainer. Though it is worth to mention that anyways tf2 eagerness had to be restrainted.

St-Savin commented 2 years ago

I did add :

import tensorflow as tf tf.compat.v1.disable_v2_behavior()

but now I have this error:

TypeError: Tensors are unhashable. (KerasTensor(type_spec=TensorSpec(shape=(?, 30, 27), dtype=tf.float32, name='module_wrapper_1_input'), name='module_wrapper_1_input', description="created by layer 'module_wrapper_1_input'"))Instead, use tensor.ref() as the key.

I am trying to use DeepExplainer on a GRU model.

thecml commented 2 years ago

@St-Savin Make sure to add it at the very beginning when you import tf the first time. I got the same error as you did when I did it later on in my notebook.

Though this is still a real issue when using TF 2.5 and Shap 0.37. The workaround with "tf.compat.v1.disable_v2_behavior()" does work, but introduces some side effects for me, one of them is doubled training times.

St-Savin commented 2 years ago

Thanks, I thought "tf.compat.v1.disable_v2_behavior() was supposed to be before importing SHAP and I was compiling and fitting the model before "tf.compat.v1.disable_v2_behavior()". Now it works by putting "tf.compat.v1.disable_v2_behavior()" before everything else. Thanks for your patience, my programming level is just above copy/paste/pray, any help is greatly appreciated.

anupam2505 commented 2 years ago

@St-Savin @thecml - I am facing the similar issue as well. but my model is trained by somebody else. And I am using this model to provide shap explanation. I am using DeepExplainer on a DNN model. I am getting this error raise TypeError("Tensor is unhashable. " "Instead, use tensor.ref() as the key.") E TypeError: Tensor is unhashable. Instead, use tensor.ref() as the key. I a putting these lines on the top but still same issue import tensorflow as tf from tensorflow.python.framework.ops import disable_eager_execution disable_eager_execution() tf.compat.v1.disable_eager_execution() What I am seeing is that executing_eagerly_outside_functions is becoming true after tf_graph.as_default(): line

saricjelena commented 2 years ago

Any updates on this issue? Are there any plans for this to be fixed or Tensorflow versions >= 2.4.0 will not be supported?

github-actions[bot] commented 1 week ago

This issue has been inactive for two years, so it's been automatically marked as 'stale'.

We value your input! If this issue is still relevant, please leave a comment below. This will remove the 'stale' label and keep it open.

If there's no activity in the next 90 days the issue will be closed.