gpt4 book ai didi

python - 在 TensorFlow2 中使用 GradientTape() 计算偏导数的问题

转载 作者:行者123 更新时间:2023-12-04 10:09:10 25 4
gpt4 key购买 nike

我在使用 TensorFlow 中的自动微分计算梯度时遇到问题。基本上我想创建一个神经网络,它只有一个输出值 f 并获得两个值(x,t)的输入。网络应该像一个数学函数,所以在这种情况下 f(x,t) 其中 x 和 t 是输入变量,我想计算偏导数,例如 df_dx, d2f/dx2df_dt .稍后我需要这些偏导数用于特定的损失函数。
这是我的简化代码:

import numpy as np
import tensorflow as tf
from tensorflow.keras.layers import Dense, Flatten
from tensorflow.keras import Model


class MyModel(Model):
def __init__(self):
super(MyModel, self).__init__()
self.flatten = Flatten(input_shape=(2, 1))
self.d1 = Dense(28)
self.f = Dense(1)

def call(self, y):
y = self.flatten(y)
y = self.d1(y)
y = self.f(y)
return y

if __name__ == "__main__":

#inp contains the input-variables (x,t)
inp = np.random.rand(1,2,1)
inp_tf = tf.convert_to_tensor(inp, np.float32)

#Create a Model
model = MyModel()

#Here comes the important part:
x = inp_tf[0][0]
t = inp_tf[0][1]

with tf.GradientTape(persistent=True) as tape:
tape.watch(inp_tf[0][0])
tape.watch(inp_tf)
f = model(inp_tf)

df_dx = tape.gradient(f, inp_tf[0][0]) #Derivative df_dx
grad_f = tape.gradient(f, inp_tf)

tf.print(f) #--> [[-0.0968768075]]
tf.print(df_dx) #--> None
tf.print(grad_f) #--> [[[0.284864038]
# [-0.243642956]]]

我期望的是我得到 df_dx = [0.284864038] (grad_f 的第一个组件),但结果是 None .我的问题是:
  • 是否可以将 f 的偏导数仅用于一个输入变量?
  • 如果是:我必须在我的代码中更改计算 df_dx 不会导致 None ?

  • 我认为可以做的是修改 class MyModel 的架构我使用两个不同的 Inputlayer(一个用于 x,一个用于 t),这样我就可以像 f = model(x,t) 这样的模型调用但这对我来说似乎不自然,我认为应该有一种更简单的方法。

    另一点是,当我将 Flattenlayer 的 input_shape 更改为 self.flatten = Flatten(input_shape=(5,1) 时,我没有收到错误消息。但是我的输入向量具有形状(1,2,1),所以我希望得到一个错误,但事实并非如此,为什么?我很感激你的帮助:)

    我使用以下配置:
  • 带有 Python 扩展作为 IDE 的 Visual Studio 代码
  • Python 版本:3.7.6
  • TensorFlow 版本:2.1.0
  • Keras 版本:2.2.4-tf
  • 最佳答案

    每次做 inp_tf[0][0]inp_tf[0][1]您正在创建一个新张量,但该新张量未用作模型的输入,inp_tf是。即使 inp_tf[0][0]如果 inp_tf 的一部分,从TensorFlow的角度来看,你新创建的inp_tf[0][0]之间没有计算图。和 f ,因此没有梯度。您必须计算关于 inp_tf 的梯度然后从那里获取您想要的渐变部分。

    除此之外,如 tf.GradientTape 的文档中所示,您可以使用嵌套磁带来计算二阶导数。而且,如果您使用 jacobian ,您可以避免使用 persistent=True ,这对性能更好。这是它在您的示例中的工作方式(我将层激活函数更改为 sigmoid ,因为默认的线性激活没有二阶导数)。

    import numpy as np
    import tensorflow as tf
    from tensorflow.keras.layers import Dense, Flatten
    from tensorflow.keras import Model

    class MyModel(Model):
    def __init__(self):
    super(MyModel, self).__init__()
    self.flatten = Flatten(input_shape=(2, 1))
    self.d1 = Dense(28, activation='sigmoid')
    self.f = Dense(1, activation='sigmoid')

    def call(self, y):
    y = self.flatten(y)
    y = self.d1(y)
    y = self.f(y)
    return y

    np.random.seed(0)
    inp = np.random.rand(1, 2, 1)
    inp_tf = tf.convert_to_tensor(inp, np.float32)
    model = MyModel()
    with tf.GradientTape() as tape:
    tape.watch(inp_tf)
    with tf.GradientTape() as tape2:
    tape2.watch(inp_tf)
    f = model(inp_tf)
    grad_f = tape2.gradient(f, inp_tf)
    df_dx = grad_f[0, 0]
    df_dt = grad_f[0, 1]
    j = tape.jacobian(grad_f, inp_tf)
    d2f_dx2 = j[0, 0, :, 0, 0]
    d2f_dyx = j[0, 0, :, 0, 1]
    d2f_dy2 = j[0, 1, :, 0, 1]
    d2f_dxy = j[0, 1, :, 0, 0]

    tf.print(df_dx)
    # [0.0104712956]
    tf.print(df_dt)
    # [-0.00301733566]
    tf.print(d2f_dx2)
    # [[-0.000243180315]]
    tf.print(d2f_dyx)
    # [[-0.000740956515]]
    tf.print(d2f_dy2)
    # [[1.49392872e-05]]
    tf.print(d2f_dxy)
    # [[-0.000740956573]]

    关于python - 在 TensorFlow2 中使用 GradientTape() 计算偏导数的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61410282/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com