Tensorflow の新しい熱心な実行モードを使用して、 http://www.hackevolve.com/where-cnn-is-Looking-grad-cam/のガイドに従ってみようとしています。特に次の 1 行に困惑しました。
grads = K.gradients(class_output, last_conv_layer.output)[0]
最後の畳み込み層と特定のクラスの出力の間の勾配を見つけていることを理解しています。ただし、を使用してこれを達成する方法を理解できませんGradientTape
。(a) 両方ともテンソルで変数ではなく、(b) 一方が他方から直接導出されていないためです (それらの特徴マップは既に存在するため、グラフがなければ効果的に独立しています)。 )。
編集:いくつかの詳細情報。回答者はまだいないので、先に進み、質問を投稿してから試したことを追加します。
明らかな手順は、Eager 実行で最初の部分を再現することです。
import numpy as np
import cv2
import tensorflow as tf
tf.enable_eager_execution()
model = tf.keras.models.load_model("model.h5")
print(type(model))
# tensorflow.python.keras.engine.sequential.Sequential
from dataset import prepare_dataset
_, ds, _, _, _, _ = prepare_dataset() # ds is a tf.data.Dataset
print(type(ds))
# tensorflow.python.data.ops.dataset_ops.DatasetV1Adapter
it = train_ds.make_one_shot_iterator()
img, label = it.get_next()
print(type(img), img.shape)
# <class 'tensorflow.python.framework.ops.EagerTensor'> (192, 192, 3)
print(type(label), label.shape)
# <class 'tensorflow.python.framework.ops.EagerTensor'> (2,)
img = np.expand_dims(img, axis=0)
print(img.shape)
# (1, 192, 192, 3)
predictions = model.predict(img)
print(predictions)
# array([[0.9711799 , 0.02882008]], dtype=float32)
class_idx = np.argmax(predictions[0])
print(class_idx)
# 0
class_output = model.output[:, class_idx]
print(model.output, class_output)
# Tensor("Softmax:0", shape=(?, 2), dtype=float32) Tensor("strided_slice_5:0", dtype=float32)
# I use tf.keras.layers.Activation instead of the activation parameter of conv2d,
# so last_conv_layer actually points to the layer after the last conv layer.
# Is that not correct?
last_conv_layer = model.get_layer('activation_6')
"""
Now, the fun part: how do I compute the gradient of class_output with respect to
the output of the last convolutional layer?
"""
1 つの試みは、reduce_sum と乗算を使用して目的の勾配を取得することです (class_output
ステップを無視します)。
with tf.GradientTape() as tape:
print(label)
# tf.Tensor([1. 0.], shape=(2,), dtype=float32)
y_c = tf.reduce_sum(tf.multiply(model.output, label))
print(y_c)
# Tensor("Sum_4:0", shape=(), dtype=float32)
last_conv_layer = model.get_layer('activation_6')
grad = tape.gradient(y_c, last_conv_layer.output)
ただし、このセットアップにgrad
あります。None