ITの隊長のブログ

ITの隊長のブログです。Rubyを使って仕事しています。最近も色々やっているお(^ω^ = ^ω^)

Tensorflow2系で指定したレイヤーから勾配を取得したい場合

スポンサードリンク

ハマった

import tensorflow as tf

# fine tuningしたいのでvgg16のモデルをロード
vgg16 = tf.keras.applications.VGG16(include_top=False, input_shape=(100, 100, 3))

for l in vgg16.layers:
    l.trainable = False

x = tf.keras.layers.Flatten()(vgg16.output)
x = tf.keras.layers.Dense(512, activation='relu')(x)
output = tf.keras.layers.Dense(5, activation='softmax', name='last_output')(x)
model = tf.keras.Model(inputs=vgg16.inputs, outputs=output, name='model')

model.compile(optimizer='adam', loss='categorical_crossentropy')
model.summary()

これで準備おk

Grad-Camとよばれる、CNNモデルがどこに着目して分類しているのかを確認する手法がある。

ネットで探せばKerasやらなんやらでみんなコードを載せているが、2系でやり方載っておらずドキュメントみながら試してた

import numpy as np


images = np.ones((1, 100, 100, 3))

# 予測クラスの算出
predictions = model.predict(images)
class_idx = np.argmax(predictions[0])
class_output = model.output[:, class_idx]

# 勾配を取得するための準備
layer_output = model.get_layer('last_output').output

# 勾配取得
grands = tf.gradients(class_output, layer_output)[0]

↑の最後のコードを実行するとエラーになる

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

tf.GradientTape 使えって????

使ってみる

with tf.GradientTape() as tape:
    print(tape.gradient(class_output, layer_output))

None

orz

わかった!Kerasのチュートリアル多いから、TensorflowからKerasを呼んで使ってみる

grands = tf.keras.backend.gradients(class_output, layer_output)[0]

RuntimeError: tf.gradients is not supported when eager execution is enabled. Use tf.GradientTape instead.

orz

どないせーとって思っていておおハマりして5時間.

Tensorflow2は、1系ではデフォだった、Graph modeが扱える. Eagerじゃないmodeで取得できないか試してみた.

g = tf.Graph()
with g.as_default():
    grads = tf.gradients(class_output, layer_output)[0]

grads

<tf.Tensor 'gradients/strided_slice_3_grad/StridedSliceGrad:0' shape=(None, 5) dtype=float32>

やったぜ!!!!

あっているかわからんが、とりあえず取れたので良しとする.