質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

91.37%

  • Python

    3802questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • TensorFlow

    274questions

  • Keras

    32questions

【Keras】grad-camの実装において自作の学習済モデルを作りたい…がエラーが出ます…

解決済

回答 1

投稿 2017/12/01 19:03

  • 評価
  • クリップ 0
  • VIEW 72

morishi3

score 1

前提・実現したいこと

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

該当のソースコード

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)

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

0

以下の行でインデックス外アクセスエラーが出ています。

conv_output =  [l for l in model.layers[0].layers if l.name is layer_name][0].output


のレイヤーアクセスが問題のようです。

Kerasのバージョンのせいの可能性もあるので、地道に調べるのが一番ラクかと。

print(model.layers)
print(model.layers[0].layers)
print([l for l in model.layers[0].layers])
print(layer_name)
print([l.name for l in model.layers[0].layers])

投稿 2017/12/02 15:44

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2017/12/05 14:16

    回答ありがとうございました!頑張ります!

    キャンセル

  • 2017/12/05 14:48

    内包表記内のエラーなので、インデックスアクセスが複数あって、特定できずに申し訳ないです。
    書き出しデバッグは愚直ですが、なにも考えなくてもできるので、思考停止した時に重宝します。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

ただいまの回答率

91.37%

関連した質問

同じタグがついた質問を見る

  • Python

    3802questions

    Pythonは、コードの読みやすさが特徴的なプログラミング言語の1つです。 強い型付け、動的型付けに対応しており、後方互換性がないバージョン2系とバージョン3系が使用されています。 商用製品の開発にも無料で使用でき、OSだけでなく仮想環境にも対応。Unicodeによる文字列操作をサポートしているため、日本語処理も標準で可能です。

  • TensorFlow

    274questions

  • Keras

    32questions