python Adam优化器-值错误:tf. function-decored函数尝试在非第一次调用时创建变量

drnojrws  于 2023-01-16  发布在  Python
关注(0)|答案(3)|浏览(168)

我使用的是tensorflow 2.3
下面的代码

import  tensorflow as tf

y_N= tf.Variable([1., 2., 3.],name="dd")

@tf.function
def loss():
    return -tf.reduce_mean(input_tensor=tf.reduce_sum(input_tensor=tf.math.log(y_N), axis=0))

@tf.function
def run():
    tf.keras.optimizers.Adam(0.5).minimize(loss, var_list=[y_N])

run()

例外

ValueError: tf.function-decorated function tried to create variables on non-first call.

问题看起来像tf.keras.optimizers.Adam(0.5).minimize(loss, var_list=[y_N])在使用@tf.function时在〉第一次调用时创建了新变量。如果必须将其 Package 在@tf.function下,我应该如何修改它?(真实的情况下run()是一个更大的函数)

fwzugrvs

fwzugrvs1#

我认为这可能与优化器无关。因为使用了函数装饰器,我认为我们需要启用tf.functions的渴望执行,如下所示。Source

import  tensorflow as tf
tf.config.run_functions_eagerly(True)

y_N= tf.Variable([1., 2., 3.],name="dd")

@tf.function
def loss():
    return -tf.reduce_mean(
        input_tensor=tf.reduce_sum(
            input_tensor=tf.math.log(y_N), axis=0
        )
    )

@tf.function
def run():
    tf.keras.optimizers.Adam(0.5).minimize(loss, var_list=[y_N])

run()
print(y_N)
<tf.Variable 'dd:0' shape=(3,) dtype=float32, 
numpy=array([1.5000134, 2.5000117, 3.5000103], dtype=float32)>

更新

上面的代码运行在渴望模式下会降低性能,要在图形模式下运行,首先创建optimizers.Adam类的示例,然后使用类方法,如下所示:
一个二个一个一个
您也可以查看this以获得类似的详细信息。

6g8kf2rb

6g8kf2rb2#

恐怕我无法为您提供您可能正在寻找的所有解释,因为@tf.functiondocumentation有些复杂,但根据我使用Tensorflow构建神经网络的经验,只有"运行"过程的子部分必须使用@tf.function装饰,并且这部分必须在with tf.GradientTape() as tape:内。如果我这样实现,您的代码将正常工作:

import tensorflow as tf

y_N= tf.Variable([1., 2., 3.], name="dd")

@tf.function
def loss():
    return -tf.reduce_mean(input_tensor=tf.reduce_sum(
                           input_tensor=tf.math.log(y_N), axis=0))

def run():
    with tf.GradientTape() as tape:
        tf.keras.optimizers.Adam(0.5).minimize(loss, var_list=[y_N])

run()

print(y_N)
<tf.Variable 'dd:0' shape=(3,) dtype=float32, numpy=array([1.4999985, 2.499997 , 
    3.4999952], dtype=float32)>
lb3vh1jj

lb3vh1jj3#

我发现在调用minimize函数之后,它将通过调用self.iterations一次来创建一个iter变量。(这发生在tensorflow/python/keras/optimizer_v2/optimizer_v2.py中)
随后调用self.iterations将不会创建新变量-因为iter已经创建。
因此,通过调用使其工作,我们需要在外部创建一次optimizer,并将其传递给@tf.function.它仍然会在minimize函数中创建变量,但它只会做一次,因为我们不会重复创建Adam模型。

import  tensorflow as tf

y_N= tf.Variable([1., 2., 3.],name="dd")

@tf.function
def loss():
    return -tf.reduce_mean(input_tensor=tf.reduce_sum(input_tensor=tf.math.log(y_N), axis=0))

@tf.function
def run(adam):
    adam.minimize(loss, var_list=[y_N])

adam=tf.keras.optimizers.Adam(0.5)

run(adam)

相关问题