Python 如果条件输出,则用@tf.function修饰

Python 如果条件输出,则用@tf.function修饰,python,tensorflow,tensorflow2.0,Python,Tensorflow,Tensorflow2.0,我试图评估变量a是否为空(即hassize==0)。但是,当使用@tf.function装饰代码时,if语句的计算结果错误地为True,而当删除装饰器时,它的计算结果为Falsetf.size(a)似乎在这两种情况下都正确地计算为0。如何解决这个问题 将tensorflow导入为tf a=tf.Variable([[])) @功能 def测试(a): 打印尺寸=tf.print(tf.size(a)) 印刷品(tf.尺寸(a)) 如果tf.math.不相等(tf.size(a),0): 打印('

我试图评估变量a是否为空(即has
size==0
)。但是,当使用
@tf.function
装饰代码时,if语句的计算结果错误地为True,而当删除装饰器时,它的计算结果为False
tf.size(a)
似乎在这两种情况下都正确地计算为0。如何解决这个问题

将tensorflow导入为tf
a=tf.Variable([[]))
@功能
def测试(a):
打印尺寸=tf.print(tf.size(a))
印刷品(tf.尺寸(a))
如果tf.math.不相等(tf.size(a),0):
打印('失败')
使用tf.control_依赖项([print_op]):
一无所获
测试(a)

这有点让人头疼,但是,一旦我们了解到
tf.function
正在将python操作和控制流映射到tf图,而裸函数只是急切地执行,我们就可以通过它进行挑选,这就更有意义了

我已经调整了你的例子来说明发生了什么。考虑<代码> TEST1和<代码> TEST2如下:

@tf.function
def测试1(a):
打印尺寸=tf.print(tf.size(a))
打印(“python打印大小:{}”。格式(tf.size(a)))
如果tf.math.不相等(tf.size(a),0):
打印('失败')
使用tf.control_依赖项([print_op]):
一无所获
def测试2(a):
打印尺寸=tf.print(tf.size(a))
打印(“python打印大小:{}”。格式(tf.size(a)))
如果tf.math.不相等(tf.size(a),0):
打印('失败')
使用tf.control_依赖项([print_op]):
一无所获
除了
@tf.function
装饰器之外,它们彼此相同

现在执行
test2(tf.Variable([[]])
将为我们提供:

0
python print size: 0
0
python print size: 0
这是我想你会期待的行为。而
test1(tf.Variable([[]))
给出:

python print size: Tensor("Size_1:0", shape=(), dtype=int32)
fail
0
关于此输出,您可能会发现一些令人惊讶的事情(除了
失败
):

  • print()
  • print()
    tf.print()
    的顺序颠倒了
这是因为通过添加
@tf.function
我们不再拥有python函数,而是使用autograph从函数代码映射tf图。这意味着,在计算
if
条件时,我们还没有执行
tf.math.not_equal(tf.size(a),0)
,只有一个对象(一个
Tensor
对象的实例),在python中,它是真实的:

class-MyClass:
通过
my_obj=MyClass()
如果(我的目标):
打印(“我的对象计算为真”)##输出“我的对象计算为真”
这意味着,在计算
tf.math.not_equal(tf.size(a),0)
之前,我们在
test1
中得到
print('fail')
语句

那么解决办法是什么

好的,如果我们在
if
块中删除对python only
print()
函数的调用,并将其替换为对签名友好的
tf.print()
语句,那么签名将无缝地转换我们的
if。。。else…
将逻辑转换为图形友好的
tf.cond
语句,以确保一切按正确顺序进行:

def test3(a): print_op = tf.print(tf.size(a)) print("python print size: {}".format(tf.size(a))) if tf.math.not_equal(tf.size(a),0): tf.print('fail') with tf.control_dependencies([print_op]): return None