2016-02-29 70 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