如何获得 keras 模型相对于其输入的梯度?

qua*_*ant 6 keras tensorflow2.0

我只是问了一个关于相同主题的问题,但针对自定义模型(如何在 Keras 中找到自定义模型的衍生物?)但很快意识到这是在我可以走路之前尝试运行,因此该问题已被标记为重复这个的。

我试图简化我的场景,现在有一个(非自定义)keras模型由 2Dense层组成:

inputs = tf.keras.Input((cols,), name='input')

layer_1 = tf.keras.layers.Dense(
        10,
        name='layer_1',
        input_dim=cols,
        use_bias=True,
        kernel_initializer=tf.constant_initializer(0.5),
        bias_initializer=tf.constant_initializer(0.1))(inputs)

outputs = tf.keras.layers.Dense(
        1,
        name='alpha',
        use_bias=True,
        kernel_initializer=tf.constant_initializer(0.1),
        bias_initializer=tf.constant_initializer(0))(layer_1)

model = tf.keras.Model(inputs=inputs, outputs=outputs)

prediction = model.predict(input_data)
# gradients = ...
Run Code Online (Sandbox Code Playgroud)

现在我想知道outputs关于inputsfor inputs=的导数input_data

到目前为止我尝试过的:

This answer to a different question建议运行grads = K.gradients(model.output, model.input). 但是,如果我运行它,则会出现此错误;

启用急切执行时不支持 tf.gradients。使用 tf.GradientTape 代替。

我只能假设这与现在默认的急切执行有关。

另一种方法是回答我关于自定义 keras 模型的问题,其中包括添加以下内容:

with tf.GradientTape() as tape:
    x = tf.Variable(np.random.normal(size=(10, rows, cols)), dtype=tf.float32)
    out = model(x)
Run Code Online (Sandbox Code Playgroud)

我不明白这种方法是我应该如何加载数据。它需要x是一个variable,但 myx是一个tf.keras.Input对象。我也不明白那with句话在做什么,某种魔法,但我不明白。

这里有一个与此非常相似的问题:使用 Keras Tensorflow 2.0 获取梯度,尽管应用程序和场景大不相同,我很难将答案应用于此场景。它确实让我将以下内容添加到我的代码中:

with tf.GradientTape() as t:
    t.watch(outputs)
Run Code Online (Sandbox Code Playgroud)

那确实有效,但现在呢?我跑了model.predict(...),但是我怎么得到我的渐变呢?答案说我应该跑t.gradient(outputs, x_tensor).numpy(),但我投入什么x_tensor?我没有输入变量。我尝试在运行t.gradient(outputs, model.inputs)后运行predict,但结果是:

在此处输入图片说明

qua*_*ant 5

我最终得到了这个问题的答案的变体:Get Gradients with Keras Tensorflow 2.0

x_tensor = tf.convert_to_tensor(input_data, dtype=tf.float32)
with tf.GradientTape() as t:
    t.watch(x_tensor)
    output = model(x_tensor)

result = output
gradients = t.gradient(output, x_tensor)
Run Code Online (Sandbox Code Playgroud)

这使我无需冗余计算即可获得输出和梯度。