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

How do I get the gradient of a keras model with respect to its inputs?

我刚刚问了一个关于同一主题但针对自定义模型的问题 (),但很快意识到这是在 运行 我可以走路之前尝试,所以该问题已被标记为这个的副本。

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

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 = ...

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

到目前为止我已经尝试过:

建议运行宁grads = K.gradients(model.output, model.input)。但是,如果我 运行 我得到这个错误;

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

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

另一种方法是在回答我关于自定义 keras 模型的问题时添加以下内容:

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

我不明白这种方法是我应该如何加载数据。它要求 x 是一个 variable,但我的 x 是一个 tf.keras.Input 对象。我也不明白 with 语句在做什么,有点神奇,但我不明白。

这里有一个听起来非常相似的问题: 尽管应用程序和场景差异很大,我很难将答案应用到这个场景中。它确实引导我将以下内容添加到我的代码中:

with tf.GradientTape() as t:
    t.watch(outputs)

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

我最终使用这个问题的变体答案来解决这个问题:

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)

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