【问题标题】:How do I get the gradient of a keras model with respect to its inputs?如何获得 keras 模型相对于其输入的梯度?
【发布时间】:2020-01-04 12:44:05
【问题描述】:

我刚刚问了一个关于同一主题的问题,但针对自定义模型 (How do I find the derivative of a custom model in Keras?),但很快意识到这是在我可以走路之前尝试运行,因此该问题已被标记为与此问题重复。

我试图简化我的场景,现在有一个(非自定义)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

到目前为止我所做的尝试:

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

启用 Eager Execution 时不支持 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)

我对这种方法的不理解是我应该如何加载数据。它要求xvariable,但我的xtf.keras.Input 对象。我也不明白with 声明在做什么,某种魔法,但我不明白。

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

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

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

【问题讨论】:

  • 这与您之前的问题有何不同?在 Keras 中,所有模型都是自定义的。
  • @MatiasValdenegro 它有所不同,因为我不再创建从 tf.keras.Model 继承的自定义模型类。有关更多信息,请参阅:tensorflow.org/guide/keras/custom_layers_and_models
  • 这不会改变梯度的计算方式,因此解决方案是相同的,因此是相同的问题。
  • @MatiasValdenegro 请随时回答我的任何一个问题。答案仍然难以捉摸!
  • @YOLO 权重不是渐变。

标签: keras tensorflow2.0


【解决方案1】:

我最终得到了这个问题的答案的变体: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)

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

【讨论】:

  • 真的需要将输入的numpy数组转换为张量吗?如果没有它,它可能会起作用。
  • 我认为你不需要watch。我一直在使用 GradientTape 在 Eager 模式下训练很多模型。我从未使用过watch
  • @MatiasValdenegro,我不确定,但也许,因为他们试图获得与数据相关的“梯度”,因此数据有可能需要成为其中的张量案例?
  • @MatiasValdenegro .numpy() 不是必需的。我会删除它。
  • @DanielMöller 我尝试删除 watch 但如果我这样做,t.gradient 会返回 NoneType。我认为这与张量是否“可训练”有关。我使用scipy 进行训练,所以keras 可能无法将权重识别为可训练。
猜你喜欢
  • 1970-01-01
  • 2020-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-01-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多