marcoancona / DeepExplain

A unified framework of perturbation and gradient-based attribution methods for Deep Neural Networks interpretability. DeepExplain also includes support for Shapley Values sampling. (ICLR 2018)
https://arxiv.org/abs/1711.06104
MIT License
725 stars 133 forks source link

Apply Deep Explain on LR #21

Closed tangxuning closed 6 years ago

tangxuning commented 6 years ago

Hi!

Thanks for sharing your code. This is extremely helpful!

I know my question might be dumb. I want to use your technique to explain a simple logistic regression model (implemented in keras). But I couldn't make it work. Below is the code.

import pandas as pd import numpy as np from time import time from keras.preprocessing.text import Tokenizer from keras.models import Sequential, Model from keras.regularizers import L1L2 from keras.utils import np_utils from keras.layers import Activation, Dense from keras import backend as K from sklearn.preprocessing import LabelBinarizer from sklearn.feature_extraction.text import CountVectorizer from sklearn.datasets import fetch_20newsgroups

Import DeepExplain

from deepexplain.tensorflow import DeepExplain

use_sklearn = True vocab_size = 2**14 nb_cat = 2 batch_size = 100 nb_epoch = 10 cats = ['sci.med', 'sci.space'] newsgroups_train = fetch_20newsgroups(subset='train',categories=cats) newsgroups_test = fetch_20newsgroups(subset='test',categories=cats)

print("Loading dataset...") t0 = time() print("Training set size: %d" % (newsgroups_train.filenames.shape)) print("Testing set size: %d" % (newsgroups_test.filenames.shape)) print("done in %0.3fs.\n" % (time() - t0))

print("Convert targets...") t0 = time() y_train = np_utils.to_categorical(newsgroups_train.target, nb_cat) y_test = np_utils.to_categorical(newsgroups_test.target, nb_cat) print("done in %0.3fs.\n" % (time() - t0))

print("Extracting train features...") tf_vectorizer = CountVectorizer(strip_accents = 'unicode',stop_words = 'english', max_features=vocab_size,lowercase = True, max_df = 0.95, min_df = 5) t0 = time() X_train = tf_vectorizer.fit_transform(newsgroups_train.data) vocab_size = X_train.shape[1] X_test = tf_vectorizer.transform(newsgroups_test.data) print("done in %0.3fs.\n" % (time() - t0))

model = Sequential() model.add(Dense(nb_cat, input_dim=vocab_size, kernel_regularizer=L1L2(l1=0.0, l2=0.1), activation='softmax'))

model.compile(optimizer='sgd', loss='categorical_crossentropy', metrics=['accuracy']) history = model.fit(X_train, y_train, batch_size=batch_size, nb_epoch=nb_epoch,verbose=1, validation_data=(X_test, y_test)) score = model.evaluate(X_test, y_test, verbose=0) print('loss:', score[0]) print('accuracy:', score[1])

with DeepExplain(session=K.get_session()) as de: # <-- init DeepExplain context

Need to reconstruct the graph in DeepExplain context, using the same weights.

# With Keras this is very easy:
# 1. Get the input tensor to the original model
input_tensor = model.layers[0].input

# 2. We now target the output of the last dense layer (pre-softmax)
#fModel = Model(inputs=input_tensor, outputs = model.layers[-1].output)
fModel = Model(inputs=input_tensor, outputs = model.outputs)
target_tensor = fModel(input_tensor)
xs = X_test[0:10]
ys = [1,0]
attributions = de.explain('grad*input',  target_tensor*ys, input_tensor, xs)
print ("Attributions:\n", attributions)

---------and here is the error (I believe I might use incorrect parameters in de.explain(), but not sure how to correct it)-------------------

DeepExplain: running "gradinput" explanation method (2) Model with multiple inputs: False Traceback (most recent call last): File "explain_20newsgroup.py", line 97, in attributions = de.explain('gradinput', target_tensor*ys, input_tensor, xs) File "/home/ubuntu/src/deepexplain/deepexplain/tensorflow/methods.py", line 457, in explain result = method.run() File "/home/ubuntu/src/deepexplain/deepexplain/tensorflow/methods.py", line 125, in run results = self.session_run(attributions, self.xs) File "/home/ubuntu/src/deepexplain/deepexplain/tensorflow/methods.py", line 91, in session_run return self.session.run(T, feed_dict) File "/home/ubuntu/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 877, in run run_metadata_ptr) File "/home/ubuntu/anaconda3/lib/python3.6/site-packages/tensorflow/python/client/session.py", line 1069, in _run np_val = np.asarray(subfeed_val, dtype=subfeed_dtype) File "/home/ubuntu/anaconda3/lib/python3.6/site-packages/numpy/core/numeric.py", line 492, in asarray return array(a, dtype, copy=False, order=order) ValueError: setting an array element with a sequence.

Thank you in advanced for your help!!!

tangxuning commented 6 years ago

Hi!

I figured it's because I didn't use the correct data structure. In the code above, xs is a spicy matrix. I will need to use toarray() to explicitly convert it to a numpy array before feeding it to explain.

Thanks!

marcoancona commented 6 years ago

Good, seems that this can be closed :)