Tensorflow 组合条件和控制依赖项

Tensorflow 组合条件和控制依赖项,tensorflow,Tensorflow,我试图执行一段有条件的代码,这段代码又依赖于首先执行的另一个op。此工作的简单版本,如下所示: x = tf.Variable(0.) x_op = tf.assign(x, 1.) with tf.control_dependencies([x_op]): true_fun = lambda: tf.assign_add(x, 3.) false_fun = lambda: tf.constant([]) pred = tf.constant(True) c

我试图执行一段有条件的代码,这段代码又依赖于首先执行的另一个op。此工作的简单版本,如下所示:

x = tf.Variable(0.)
x_op = tf.assign(x, 1.)

with tf.control_dependencies([x_op]):
    true_fun  = lambda: tf.assign_add(x, 3.)
    false_fun = lambda: tf.constant([])
    pred = tf.constant(True)
    cond_op = control_flow_ops.cond(pred, true_fun, false_fun)
其中,评估
cond_op
x
设置为
4.0
。但是,这个更复杂的版本不起作用:

def rest(x): tf.gather(x, tf.range(1, tf.size(x)))

x = tf.Variable([0., 1.])
x_op = tf.assign(x, [0., 1., 2.], validate_shape=False)

with tf.control_dependencies([x_op]):
    true_fun  = lambda: tf.assign(x, rest(x), validate_shape=False)
    false_fun = lambda: tf.constant([])
    pred = tf.constant(True)
    cond_op = control_flow_ops.cond(pred, true_fun, false_fun)

特别是
x
被分配
[1.]
而不是
[1,2.]
。我要使用的逻辑是,首先将
x
赋值为
[0,1,2.]
,然后将其修剪为
[1,2.]
。顺便说一句,这似乎与
x
的大小变化有关,因为如果在初始
x\u op
赋值中
x
被赋值
[1,2.]
而不是
[0,1,2.]
,那么计算
cond\u op
会导致
x
被赋值
[2.]
,这是正确的行为。即,它首先更新为
[1,2.]
,然后修剪为
[2.]

注意带有tf.control\u依赖项的
仅适用于在块内创建的操作。当您在块内调用
rest(x)
时,您所指的
x
仍然是旧的
x
,它是
tf.Variable
函数的返回值,它只是保存变量初始值的
张量。您可以通过调用
rest(x_op)
来传递新值。下面是完整的工作片段:

import tensorflow as tf

def rest(x): return tf.gather(x, tf.range(1, tf.size(x)))

x = tf.Variable([0., 1.])
x_op = tf.assign(x, [0., 1., 2.], validate_shape=False)

with tf.control_dependencies([x_op]):
  true_fun  = lambda: tf.assign(x, rest(x_op), validate_shape=False)
  false_fun = lambda: tf.constant([])
  pred = tf.constant(True)
  cond_op = tf.cond(pred, true_fun, false_fun)

with tf.Session(""):
  x.initializer.run()
  print(cond_op.eval())

请注意,带有tf.control_依赖项的
仅适用于在块内创建的操作。当您在块内调用
rest(x)
时,您所指的
x
仍然是旧的
x
,它是
tf.Variable
函数的返回值,它只是保存变量初始值的
张量。您可以通过调用
rest(x_op)
来传递新值。下面是完整的工作片段:

import tensorflow as tf

def rest(x): return tf.gather(x, tf.range(1, tf.size(x)))

x = tf.Variable([0., 1.])
x_op = tf.assign(x, [0., 1., 2.], validate_shape=False)

with tf.control_dependencies([x_op]):
  true_fun  = lambda: tf.assign(x, rest(x_op), validate_shape=False)
  false_fun = lambda: tf.constant([])
  pred = tf.constant(True)
  cond_op = tf.cond(pred, true_fun, false_fun)

with tf.Session(""):
  x.initializer.run()
  print(cond_op.eval())

谢谢你的澄清。上述方法确实有效,解决了我的问题。一个问题:我尝试将
tf.get_variable
放在
control_dependencies
块中,以获取
x
的新副本(除了使用正确的变量范围和启用变量重用等),但这不起作用。为什么不呢?如果我在依赖项块中获得了
x
的新副本,它不应该检索新值吗?我发现这种行为有点令人困惑。根据文档,tf.assign(ref,value)在赋值完成后返回ref。x和x_op的返回值之间的差异是什么?你有其他信息的链接吗?谢谢你的澄清。上述方法确实有效,解决了我的问题。一个问题:我尝试将
tf.get_variable
放在
control_dependencies
块中,以获取
x
的新副本(除了使用正确的变量范围和启用变量重用等),但这不起作用。为什么不呢?如果我在依赖项块中获得了
x
的新副本,它不应该检索新值吗?我发现这种行为有点令人困惑。根据文档,tf.assign(ref,value)在赋值完成后返回ref。x和x_op的返回值之间的差异是什么?你有其他信息的链接吗?