4
$\begingroup$

I'm following the text classification with movie reviews TensorFlow tutorial, and wanted to extend the project by looking, for a certain input, which words influenced the classification the most.

I understand this is called a saliency map, but I'm having trouble calculating it. I believe that I need to calculate the gradients of the output with respect to the input. I tried to implement code similar to the code in this answer to no avail. A confounding issue is that the model uses an embedding layer, which doesn't propagate the gradient, so I think one needs to calculate the gradients with the input being the output of the embedding layer.

It's probably wrong for all sorts of reasons, but this is the closest I've gotten with the Python code:

# Create the saliency function
input_tensors = [model.layers[1].input, keras.backend.learning_phase()]
model_input = model.layers[1].input
model_output = model.output
gradients = model.optimizer.get_gradients(model_output, model_input)
compute_gradients = keras.backend.function(inputs=input_tensors, outputs=gradients)

# Word encoding
idx = 0 # Calculate the saliency for the first training example
embeddings = model.layers[0].get_weights()[0]
embedded_training_data = embeddings[train_data[idx]]
matrix = compute_gradients([embedded_training_data.reshape(sum([(1,), embedded_training_data.shape], ())), train_labels[idx]])

But the final matrix is the same row repeated and I'm not sure how to interpret it. Any help would be greatly appreciated. Thankfully, as this is extending a tutorial, there is a complete working example of the code!

$\endgroup$

1 Answer 1

0
$\begingroup$

I've been working on this for the last few days, and I think I've answered my own question. Calculating individual word saliency is not possible with the model structure as is. This is because of the GlobalAveragePooling layer of the model. This averages the embedding matrix in the 'word' dimension, removing the ability to distinguish the effect of an individual word on the classification. This is the code I used to convince myself of what was happening, left here in the hope that the next soul to try this finds this answer.

outputTensor = model.output

embeddingTensor = model.layers[1].input
gradientsEmbedding = tf.gradients(outputTensor, embeddingTensor)

globalAverageTensor = model.layers[2].input
gradientsAverage = tf.gradients(outputTensor, globalAverageTensor)

idx = 1

sess = keras.backend.get_session()

embedding = sess.run(embeddingTensor, feed_dict={model.input:train_data[(idx-1):idx,:]})
globalAverage = sess.run(model.layers[2].input, feed_dict={model.input:train_data[(idx-1):idx,:]})

print(np.mean(embedding, 1))
print(globalAverage)

gradientMatrixEmbedding = sess.run(gradientsEmbedding, feed_dict={embeddingTensor:embedding})
gradientMatrixAverage = sess.run(gradientsAverage, feed_dict={globalAverageTensor:globalAverage})

print(np.sum(gradientMatrixEmbedding, 2))
print(gradientMatrixAverage)
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.