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

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

ただいまの
回答率

90.75%

  • Python 3.x

    5291questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • TensorFlow

    601questions

CNNで生成したモデルをGradCAMアルゴリズムで可視化したい

受付中

回答 1

投稿 編集

  • 評価
  • クリップ 2
  • VIEW 1,642

calm

score 2

初めまして,深層学習を学んでいる者です。
現在,CNNで画像を学習し,5つの物体の画像認識をしています。
CNNで生成したモデルの可視化を行うために,Grad-CAMアルゴリズムを調べました。
参考URL1では,University of Oxford の VGG チームが生成したVGGモデルから特徴量の可視化を行っていました。
このソースコードを自分の作ったモデル(gradcam.npz)で可視化を行いたいのですが
以下のエラーメッセージが発生しました。どなたか分かる人がいたらご教授お願い致します。
また,自分の質問に何か不備なところがありましたらご指摘の方よろしくお願いいたします。

主な環境

Anaconda3
tensorflow (1.2.1)
tensorlayer (1.6.5)
python (3.5)

発生している問題・エラーメッセージ

フォルダ>python mainmodel.py --input laska.png --output laska_save.png --layer_name pool2

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "mainmodel.py", line 103, in <module>
    tf.app.run()
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\platform\app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "mainmodel.py", line 72, in main
    vgg = vgg16(imgs, 'gradcam.npz', sess)
  File "C:\Ana3\tutorialGradCAM\vgg.py", line 23, in __init__
    self.load_weights(weights, sess)
  File "C:\Ana3\tutorialGradCAM\vgg.py", line 274, in load_weights
    sess.run(self.parameters[i].assign(weights[k]))
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\ops\variables.py", line 516, in assign
    return state_ops.assign(self._variable, value, use_locking=use_locking)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\ops\state_ops.py", line 271, in assign
    validate_shape=validate_shape)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\ops\gen_state_ops.py", line 45, in assign
    use_locking=use_locking, name=name)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\op_def_library.py", line 767, in apply_op
    op_def=op_def)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\ops.py", line 2508, in create_op
    set_shapes_for_outputs(ret)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\ops.py", line 1873, in set_shapes_for_outputs
    shapes = shape_func(op)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\ops.py", line 1823, in call_with_requiring
    return call_cpp_shape_fn(op, require_shape_fn=True)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 610, in call_cpp_shape_fn
    debug_python_shape_fn, require_shape_fn)
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 676, in _call_cpp_shape_fn_impl
    raise ValueError(err.message)
ValueError: Shapes must be equal rank, but are 4 and 1 for 'Assign' (op: 'Assign') with input shapes: [3,3,3,64], [0].

GradCAMで可視化するためのソースコード

from vgg import vgg16
import tensorflow as tf
import numpy as np
from skimage import io
from skimage.transform import resize
from matplotlib import pyplot as plt
from imagenet_classes import class_names
from scipy.misc import imread, imresize

flags = tf.app.flags
flags.DEFINE_string("input", "ab.jpg", "Path to input image ['ab.jpg']")
flags.DEFINE_string("output", "abs.jpg", "Path to input image ['abs.jpg']")
flags.DEFINE_string("layer_name", "pool5", "Layer till which to backpropagate ['pool5']")

FLAGS = flags.FLAGS


def load_image(img_path):
    print("Loading image")
    img = imread(img_path, mode='RGB')
    img = imresize(img, (56, 56))
    # Converting shape from [224,224,3] tp [1,224,224,3]
    x = np.expand_dims(img, axis=0)
    # Converting RGB to BGR for VGG
    x = x[:,:,:,::-1]
    return x, img


def grad_cam(x, vgg, sess, predicted_class, layer_name, nb_classes):
    print("Setting gradients to 1 for target class and rest to 0")
    # Conv layer tensor [?,7,7,512]
    conv_layer = vgg.layers[layer_name]
    # [1000]-D tensor with target class index set to 1 and rest as 0
    one_hot = tf.sparse_to_dense(predicted_class, [nb_classes], 1.0)
    signal = tf.multiply(vgg.layers['fc3'], one_hot)
    loss = tf.reduce_mean(signal)

    grads = tf.gradients(loss, conv_layer)[0]
    # Normalizing the gradients
    norm_grads = tf.div(grads, tf.sqrt(tf.reduce_mean(tf.square(grads))) + tf.constant(1e-5))

    output, grads_val = sess.run([conv_layer, norm_grads], feed_dict={vgg.imgs: x})
    output = output[0]           # [7,7,512]
    grads_val = grads_val[0]     # [7,7,512]

    weights = np.mean(grads_val, axis = (0, 1))             # [512]
    cam = np.ones(output.shape[0 : 2], dtype = np.float32)    # [7,7]

    # Taking a weighted average
    for i, w in enumerate(weights):
        cam += w * output[:, :, i]

    # Passing through ReLU
    cam = np.maximum(cam, 0)
    cam = cam / np.max(cam)
    cam = resize(cam, (56,56))

    # Converting grayscale to 3-D
    cam3 = np.expand_dims(cam, axis=2)
    cam3 = np.tile(cam3,[1,1,3])

    return cam3


def main(_):
    x, img = load_image(FLAGS.input)

    sess = tf.Session()

    print("\nLoading Vgg")
    imgs = tf.placeholder(tf.float32, [None, 56, 56, 3])
    vgg = vgg16(imgs, 'gradcam.npz', sess)
#'gradcam.npz'は生成したモデル

    print("\nFeedforwarding")
    prob = sess.run(vgg.probs, feed_dict={vgg.imgs: x})[0]
    preds = (np.argsort(prob)[::-1])[0:4]
    print('\nTop 5 classes are')
    for p in preds:
        print(class_names[p], prob[p])

    # Target class
    predicted_class = preds[0]
    # Target layer for visualization
    layer_name = FLAGS.layer_name
    # Number of output classes of model being used
    nb_classes = 5

    cam3 = grad_cam(x, vgg, sess, predicted_class, layer_name, nb_classes)

    img = img.astype(float)
    img /= img.max()

    # Superimposing the visualization with the image.
    new_img = img+3*cam3
    new_img /= new_img.max()

    # Display and save
    io.imshow(new_img)
    plt.show()
    io.imsave(FLAGS.output, new_img)

if __name__ == '__main__':
    tf.app.run()

試したこと    

tensorflowのモデルファイルckptファイルをnpzファイルに変換.これは,参考URL1の生成モデルがnpzファイルだったため変換を行いました.
変換するために,tensorlayer(1.6.5)をインストールしましたた.
推測ではありますが,参考URL1ではVGGモデルでモデルの可視化を行っていました.
VGGを扱うための関数か何かを自分の生成したモデルの関数に変更すれば可視化できると考えています.

補足情報(参考文献等)

参考URL1:GradCAMによる可視化の参考文献 
main.pyでは,VGGモデルを用いて,GradCAMで可視化しました.
下に記したコマンドによりmain.pyを実行し,可視化していました.
python main.py --input laska.png --output laska_save.png --layer_name pool5
参考URL2: 生成したモデルの参考文献

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

質問への追記・修正、ベストアンサー選択の依頼

  • 退会済みユーザー

    退会済みユーザー

    2017/10/21 11:23

    teratailの方針でマルチポストは禁止はされていませんが、いくらかルールがあるようなのでそちらもご覧ください。(https://teratail.com/help)

    キャンセル

  • calm

    2017/10/21 22:12

    @slashさん すいません,マルチポストにならないように訂正しました. 以後気を付けます.

    キャンセル

  • 退会済みユーザー

    退会済みユーザー

    2017/10/22 10:13

    たぶん、teratailは「マルチポストはやっても良いいけれども、片方(例えばStackoverflow)で分かったことがもう片方(例えばTeratail)ではまだ分かっていないというような、情報共有がうまくいかないのが(ムダな手間につながるから)いけないよ」ということだと思います o.0

    キャンセル

回答 1

+1

同じデータを共有することはたぶんできないですよね…

誰もやったことのないことをやられているようですし、同じモデルを他の人が持っているわけではないので、やってみて走らせて、エラーを見ながら、最後に解決できるのはcalmさんしかいないと思います。

なので、怪しいところだけを書きます。


この問題の一番のミソは、
以下のエラーメッセ―ジによれば、エラーの末端にある

  • 'Assign'に対してランク4の値が欲しいのに、ランク1のデータが渡された
    ということのようです。

そして、エラーが起きているコードのうち、calmさんが書いたコードの末端部分はvgg = vgg16(imgs, 'gradcam.npz', sess)ですね。(vgg16はかなりの人が使っているので、たぶんここでコケる原因となるバグは無いと仮定すると、)怪しいのはimgsっぽい気がします。

rankの考え方はTensorFlowのRank, Shapeについて@uyuniさんが分かりやすいと思います。

実際の解決については、NickTGrahamさんのようにネストすれば解決できると思われます。


# エラーの転記です。コードではありません。

フォルダ>python mainmodel.py --input laska.png --output laska_save.png --layer_name pool2

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "mainmodel.py", line 103, in <module>
    tf.app.run()
  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\platform\app.py", line 48, in run
    _sys.exit(main(_sys.argv[:1] + flags_passthrough))
  File "mainmodel.py", line 72, in main
    vgg = vgg16(imgs, 'gradcam.npz', sess)

# (中略:ここまでがcalmさんが書いたコード、以下そのままのコードと仮定します)

  File "C:\Ana3\envs\tensorflow\lib\site-packages\tensorflow\python\framework\common_shapes.py", line 676, in _call_cpp_shape_fn_impl
    raise ValueError(err.message)
ValueError: Shapes must be equal rank, but are 4 and 1 for 'Assign' (op: 'Assign') with input shapes: [3,3,3,64], [0].

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2017/10/22 22:32

    @slashさん
    回答ありがとうございました。問題解決に取り組みたいと思います。
    そして,マナー等も教えていただきありがとうございます。

    キャンセル

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

  • ただいまの回答率 90.75%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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

  • Python 3.x

    5291questions

    Python 3はPythonプログラミング言語の最新バージョンであり、2008年12月3日にリリースされました。

  • TensorFlow

    601questions