Tensorflow Eager Execution - 计算顺序模型两层之间的梯度

Posted

技术标签:

【中文标题】Tensorflow Eager Execution - 计算顺序模型两层之间的梯度【英文标题】:Tensorflow Eager Execution - Compute gradient between two layers of a sequential model 【发布时间】:2019-11-04 18:56:12 【问题描述】:

我正在尝试遵循http://www.hackevolve.com/where-cnn-is-looking-grad-cam/ 的指南,使用 Tensorflow 的新急切执行模式。特别是一句话让我很难过:

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?
"""

一种尝试是使用reduce_sum 和multiply 来获得所需的梯度(忽略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

【问题讨论】:

【参考方案1】:

您是否尝试将 predictions = model.predict(img) 以后的代码放入 GradientTape 上下文管理器?

问题是,如果你没有记录从last_conv_layer.outputmodel.output 的渐变,反向传播链实际上会被破坏。

【讨论】:

以上是关于Tensorflow Eager Execution - 计算顺序模型两层之间的梯度的主要内容,如果未能解决你的问题,请参考以下文章

tensorflow 神经网络模型概览;熟悉Eager 模式;

[转]tensorflow提示:No module named ''tensorflow.python.eager"

Tensorflow Eager和Tensorboard图?

AttributeError: module 'tensorflow' has no attribute 'enable_eager_execution'

Tensorflow Eager execution and interface

与 Eager 和 Graph 模式无关的 Tensorflow 训练