###前提・実現したいこと
Python(Keras)でCNNを用い2種類の画像を判別するプログラムを作っております。
その時に学習したモデルを活用して判定時にどこに注目したのかを
grad-camにより、表現したいと考えております。
grad-camについては
https://github.com/jacobgil/keras-grad-cam/blob/master/grad-cam.py
こちらのコードを参考にしており自分のモデルに合わせて対象箇所を変えたつもりです。
モデルはこちらになります。
Layer (type) Output Shape Param #
conv2d_1 (Conv2D) (None, 62, 62, 32) 896
max_pooling2d_1 (MaxPooling2 (None, 31, 31, 32) 0
dropout_1 (Dropout) (None, 31, 31, 32) 0
zero_padding2d_1 (ZeroPaddin (None, 33, 33, 32) 0
conv2d_2 (Conv2D) (None, 31, 31, 96) 27744
max_pooling2d_2 (MaxPooling2 (None, 15, 15, 96) 0
dropout_2 (Dropout) (None, 15, 15, 96) 0
zero_padding2d_2 (ZeroPaddin (None, 17, 17, 96) 0
conv2d_3 (Conv2D) (None, 15, 15, 96) 83040
max_pooling2d_3 (MaxPooling2 (None, 7, 7, 96) 0
flatten_1 (Flatten) (None, 4704) 0
dense_1 (Dense) (None, 1024) 4817920
dropout_3 (Dropout) (None, 1024) 0
dense_2 (Dense) (None, 2) 2050
Total params: 4,931,650
Trainable params: 4,931,650
Non-trainable params: 0
###発生している問題・エラーメッセージ
IndexError Traceback (most recent call last) <ipython-input-3-2fe13b62daac> in <module>() 128 129 predicted_class = np.argmax(predictions) --> 130 cam, heatmap = grad_cam(model, preprocessed_input, predicted_class, "conv2d_3") 131 cv2.imwrite("gradcam.jpg", cam) 132 <ipython-input-3-2fe13b62daac> in grad_cam(input_model, image, category_index, layer_name) 92 93 loss = K.sum(model.layers[-1].output) ---> 94 conv_output = [l for l in model.layers[0].layers if l.name is layer_name][0].output 95 grads = normalize(K.gradients(loss, conv_output)[0]) 96 gradient_function = K.function([model.layers[0].input], [conv_output, grads]) IndexError: list index out of range
###該当のソースコード
python
from keras.preprocessing import image from keras.layers.core import Lambda from keras.models import Sequential ,load_model from tensorflow.python.framework import ops import keras.backend as K import tensorflow as tf import numpy as np import keras import sys import cv2 def target_category_loss(x, category_index, nb_classes): return tf.multiply(x, K.one_hot([category_index], nb_classes)) def target_category_loss_output_shape(input_shape): return input_shape def normalize(x): # utility function to normalize a tensor by its L2 norm return x / (K.sqrt(K.mean(K.square(x))) + 1e-5) def load_image(path): img_path = path img = image.load_img(img_path, target_size=(64, 64)) x = image.img_to_array(img) x = np.expand_dims(x, axis=0) return x def register_gradient(): if "GuidedBackProp" not in ops._gradient_registry._registry: @ops.RegisterGradient("GuidedBackProp") def _GuidedBackProp(op, grad): dtype = op.inputs[0].dtype return grad * tf.cast(grad > 0., dtype) * \ tf.cast(op.inputs[0] > 0., dtype) def compile_saliency_function(model, activation_layer='conv2d_3'): input_img = model.input layer_dict = dict([(layer.name, layer) for layer in model.layers[1:]]) layer_output = layer_dict[activation_layer].output max_output = K.max(layer_output, axis=3) saliency = K.gradients(K.sum(max_output), input_img)[0] return K.function([input_img, K.learning_phase()], [saliency]) def modify_backprop(model, name): g = tf.get_default_graph() with g.gradient_override_map({'Relu': name}): # get layers that have an activation layer_dict = [layer for layer in model.layers[1:] if hasattr(layer, 'activation')] # replace relu activation for layer in layer_dict: if layer.activation == keras.activations.relu: layer.activation = tf.nn.relu # re-instanciate a new model new_model = model return new_model def deprocess_image(x): ''' Same normalization as in: https://github.com/fchollet/keras/blob/master/examples/conv_filter_visualization.py ''' if np.ndim(x) > 3: x = np.squeeze(x) # normalize tensor: center on 0., ensure std is 0.1 x -= x.mean() x /= (x.std() + 1e-5) x *= 0.1 # clip to [0, 1] x += 0.5 x = np.clip(x, 0, 1) # convert to RGB array x *= 255 if K.image_dim_ordering() == 'th': x = x.transpose((1, 2, 0)) x = np.clip(x, 0, 255).astype('uint8') return x def grad_cam(input_model, image, category_index, layer_name): model = Sequential() model.add(input_model) nb_classes = 2 target_layer = lambda x: target_category_loss(x, category_index, nb_classes) model.add(Lambda(target_layer, output_shape = target_category_loss_output_shape)) loss = K.sum(model.layers[-1].output) conv_output = [l for l in model.layers[0].layers if l.name is layer_name][0].output grads = normalize(K.gradients(loss, conv_output)[0]) gradient_function = K.function([model.layers[0].input], [conv_output, grads]) output, grads_val = gradient_function([image]) output, grads_val = output[0, :], grads_val[0, :, :, :] weights = np.mean(grads_val, axis = (0, 1)) cam = np.ones(output.shape[0 : 2], dtype = np.float32) for i, w in enumerate(weights): cam += w * output[:, :, i] cam = cv2.resize(cam, (64, 64)) cam = np.maximum(cam, 0) heatmap = cam / np.max(cam) #Return to BGR [0..255] from the preprocessed image image = image[0, :] image -= np.min(image) image = np.minimum(image, 255) cam = cv2.applyColorMap(np.uint8(255*heatmap), cv2.COLORMAP_JET) cam = np.float32(cam) + np.float32(image) cam = 255 * cam / np.max(cam) return np.uint8(cam), heatmap # 判定画像の読み込み preprocessed_input = load_image('image.jpeg') model = load_model('mymodel.h5') model.summary() predictions = model.predict(preprocessed_input) predicted_class = np.argmax(predictions) cam, heatmap = grad_cam(model, preprocessed_input, predicted_class, "conv2d_3") cv2.imwrite("gradcam.jpg", cam) register_gradient() guided_model = modify_backprop(model, 'GuidedBackProp') saliency_fn = compile_saliency_function(guided_model) saliency = saliency_fn([preprocessed_input, 0]) gradcam = saliency[0] * heatmap[..., np.newaxis] cv2.imwrite("guided_gradcam.jpg", deprocess_image(gradcam))
###試したこと
1行1行入力してみたもののどこが問題かわからず、
もともと専門外で初心者なこともあり、お手上げ状態です…
###補足情報(言語/FW/ツール等のバージョンなど)
tensorflow (1.1.0)
Keras (2.0.4)
まだ回答がついていません
会員登録して回答してみよう