2016-02-29 82 views
2

说我有可变x的一些功能f一个变量更新强制依赖

x = tf.Variable(1.0) 
fx = x*x 

和更新x运算:

new_x = x.assign(2.0) 

,我想带来的的f值从更新的x。我原以为

with tf.control_dependencies([new_x,]): 
    new_fx = tf.identity(fx)  

将迫使new_fx依赖于更新new_x,但这似乎并没有这样的情况:

init = tf.initialize_all_variables() 
sess = tf.Session() 
sess.run(init) 

# prints 1.0, expected 4.0 
print "new fx", sess.run(new_fx) 

有一些其他的方式来定义的更新值fx

很明显,我可以通过编写类似new_fx = new_x * new_x的东西来创建一个新的独立副本,但是这会炸毁图形大小,并且还需要访问fx的定义,我倾向于将其定义为黑盒子。

编辑:激励这一点,这里的代码的素描时,我想写:

# Hamiltonian Monte Carlo update, simplified 
def hmc_step(x, momentum, logpdf, n_steps=50): 
    # x and momentum are Variables 
    # logpdf is a Tensor with potentially complicated dependence on x 

    grad = tf.gradients(logpdf, x)[0] 

    # initial position   
    new_x = x 

    for i in range(n_steps): 
     # update position 
     new_x = x.assign(new_x + momentum) 

     # update momentum using gradient at *current* position 
     with tf.control_dependencies([new_x]): 
      momentum = momentum + grad # DOESN'T WORK 

     # DOES WORK BUT IS UGLY 
     # new_logpdf = define_logpdf(new_x) 
     # new_grad = tf.gradients(new_logpdf, new_x)[0] 
     # momentum = momentum + new_grad 

    # (do some stuff to accept/reject the new x) 
    # .... 

    return new_x 

感觉真的很糟糕定义logpdf并重新推导梯度通过每次循环的新副本:它需要访问define_logpdf()并将图形大小放大50倍。是否没有更好的方法来执行此操作(禁止某些等效的theano.scan)?

+1

你可以做'sess.run([一个new_x])'之后'sess.run([other_stuff])',它保证'new_x'之前'other_stuff'评估 –

+0

对。这也不是理想的,因为它将更新逻辑推送到运行时Python代码中,当我想要在TF操作系统中声明性地封装和表示声音时,但它听起来像我想要的可能只是不可能,所以这是我的选择之一会考虑的。谢谢! – davmre

回答

2

with tf.control_dependencies([op])块强制控制依赖于op其他操作创建在块内。在你的情况下,x*x在外面创建,并且tf.identity刚刚获得旧值。这里是你想要的东西:

with tf.control_dependencies([new_x,]): 
    new_fx = x*x 
+0

为什么tf.identity不会创建一个依赖new_x更新的新操作?身份不是“op”吗?我知道我可以定义一个新的函数副本,但这不是我想要的。 – davmre

+1

'tf.identity'由于控制块而在'new_x'更新后被评估。但是对'tf.identity'的输入没有任何限制,所以在更新之前可以进行评估 –

+0

谢谢,这很有道理。我更新了一些关于我在寻找什么的更多说明。这听起来像是确保在赋值之后将重新评估依赖关系的唯一方法,就是根据新分配的值明确重新定义该依赖关系? – davmre