Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

K.gradients(loss, input_img)[0] return "None". (Keras CNN visualization with tensorflow backend)

I have CNN models trained using Keras with Tensorflow backend. And I want to visualize my CNN filters with this tutorial: https://blog.keras.io/how-convolutional-neural-networks-see-the-world.html

from keras import backend as K
from keras.models import load_model
import numpy as np

model = load_model('my_cnn_model.h5')
input_img = np.load('my_picture.npy')

# get the symbolic outputs of each "key" layer (we gave them unique names).
layer_dict = dict([(layer.name, layer) for layer in model.layers])

layer_name = 'block5_conv3'
filter_index = 0  # can be any integer from 0 to 511, as there are 512 filters in that layer

# build a loss function that maximizes the activation
# of the nth filter of the layer considered
layer_output = layer_dict[layer_name].output
loss = K.mean(layer_output[:, :, :, filter_index])

# compute the gradient of the input picture wrt this loss
grads = K.gradients(loss, input_img)[0]

# normalization trick: we normalize the gradient
grads /= (K.sqrt(K.mean(K.square(grads))) + 1e-5)

# this function returns the loss and grads given the input picture
iterate = K.function([input_img], [loss, grads])

However, when the code execute to this line:
grads = K.gradients(loss, input_img)[0]
I found it returns nothing but None object, so the program fail to progress after that.

I search for some solution. Some people say theinput_img should be tensorflow's Tensor type: https://github.com/keras-team/keras/issues/5455

But when I tried to convert the img to Tensor, the problem is still exist.
I tried the solution in the link above, but still fail.

There is also someone say that this problem exists because your CNN model is not differentiable. https://github.com/keras-team/keras/issues/8478

But my model use only the activate function of ReLU and Sigmoid(at output layer). Is this problem really caused by nondifferentiable problem?

Can anyone help me? Thank you very much!

like image 255
Jexus Avatar asked Apr 14 '18 17:04

Jexus


3 Answers

If you have a Model instance, then to take the gradient of the loss with respect to the input, you should do:

grads = K.gradients(loss, model.input)[0]

model.input contains the symbolic tensor that represents the input to the model. Using a plain numpy array makes no sense because TensorFlow then has no idea how this connects to the computational graph, and returns None as the gradient.

Then you should also rewrite the iterate function as:

iterate = K.function([model.input], [loss, grads])
like image 146
Dr. Snoopy Avatar answered Oct 28 '22 12:10

Dr. Snoopy


Below, it's my example. Hope to help someone.

gradient = keras.backend.gradients(model.output, model.input)[2]

iterate = keras.backend.function(model.input, [gradient])

grad = iterate([patches, depthes, poses])

[patches, depthes, poses] is my model.input

like image 3
Fangjing Song Avatar answered Oct 28 '22 13:10

Fangjing Song


I too had faced the same error @Jexus. For me the problem was:

loss variable was None object. I had used

loss.assign_add(....)

instead of

loss = loss + .....

After changing that as mentioned, the loss was returning a tensor and hence

grads = K.gradients(loss, model.input)[0]

wasn't returning None.

like image 1
Bhanu Prakash Avatar answered Oct 28 '22 12:10

Bhanu Prakash