2016-11-18 8 views
4

Tensor Flowグラフを作成して、インクリメントする数値をキューに追加するにはどうすればよいですか?Tensorフローのエンキューとインクリメント変数

私は、学習目的のためにこれをやっているので、私はあなたが私がやっているものと同様のことを守れば好む(と私が間違ってやっている修正)と思います。

import tensorflow as tf 

# create queue 
queue = tf.RandomShuffleQueue(capacity=10, min_after_dequeue=1, dtypes=tf.float32) 

# create variables, and "add" operation 
push_var = tf.Variable(initial_value=1.0, trainable=False) 
add = push_var.assign_add(1) 

# enqueue operation 
push = queue.enqueue(add) 

# dequeue operation 
pop = queue.dequeue() 

sess = tf.InteractiveSession() 

tf.initialize_all_variables().run() 

# add var to stack 
sess.run(push) # push_var = 2 after ran 
sess.run(push) # push_var = 3 after ran 
sess.run(push) # push_var = 4 after ran 
sess.run(push) # push_var = 5 after ran 
sess.run(push) # push_var = 6 after ran 
sess.run(push) # push_var = 7 after ran 
sess.run(push) # push_var = 8 after ran 

# pop variable (random shuffle) 
print sess.run(pop) 
print sess.run(pop) 

sess.close() 

出力::私はそれは2と8はその代わりに、それは常に、変数の現在の値をポップさとの間の2つの乱数であることを期待してい

8 
8 

これは私のコードです。

これは、変数の実際の値をプッシュするのではなく、代わりにポインタを変数にプッシュするためですか?テンソルフローのdocumentation氏は述べていますassign_add戻り

添加が完了した後に、この変数の新しい値を保持しますテンソル。

繰り返しますが、私はテンソルの流れについて学ぶためにしようとしています。 TensorFlowのウェブサイト以外にも、学習リソースがあれば感謝しています。ありがとう。

EDIT:

が期待される行動のpush = queue.enqueue(add)push = queue.enqueue(add + 0)に結果を変更します。誰かがこれを説明できますか?

+0

お使いのバージョンは?私はtf.11とtf 12rc1で試してみましたが、この動作を再現することはできません。あなたのコードを試してみると、デキューが異なる数字を生成しています。 –

答えて

2

@David Wongは変数がその基礎となるテンソルへの参照に過ぎないということは正しいです。 7回押しても、キュー内の7つの要素はすべて、同じ基礎テンソルを指しています。 popが実行されると、基礎となるテンソルが参照されて返されます。

もう少し説明しましょう。 assign_add(1)は単に参照された値を更新するので、参照を返します。 push = queue.enqueue(add)を実行すると、内部的にtf.convert_to_tensor(add)が呼び出され、その入力も参照であれば参照を返します。

あなたはPythonシェルでtf.convert_to_tensor(add)の出力を検査することができます

In [2]: tf.convert_to_tensor(add) 
Out[2]: <tf.Tensor 'AssignAdd:0' shape=() dtype=float32_ref> 

dtype=float32_refは、それが参照であることを示します。

add + 0として、あなたもtf.add(add, 0)に相当しipythonシェル、それを調べることができます。

In [3]: add+0 
Out[3]: <tf.Tensor 'add:0' shape=() dtype=float32> 

それが参照ではなく、親ノードadd = push_var.assign_add(1)を持っています。

ので、ここでの問題は、

1である)、それがキューにプッシュされたときテンソルは、そのすべての親ノードが同様に評価される、評価されるでしょう。あなたのケースで

は、add + 0が評価されるので、1

2で参照される値をインクリメントし、その親ノードadd = push_assign_add(1))がキューにプッシュする際の基準が評価されません。キューには単に参照があります。それらがポップされ参照されると、それらの実際のテンソル値がフェッチされます。

あなたの場合、これらの参照はすべて同じテンソルを指しています。だからポップスはすべて8を返す。

+0

Hm、私はqueue.enqueueはテンソルの具体的な値だけを押すことができると思うので、実行中の参照の評価を強制するでしょう –

+0

@ YaroslavBulatov評価がどこで起こるかを指摘してもらえますか? – yuefengz

+0

'Enqueue'オペレーションが実行されたとき。それはTensorを取り、それを待ち行列に入れます。したがって、 'enqueue'演算を実行する前に' tens_flow'ランタイムは 'assign_add'を評価します。 'assign_add'を評価すると可変の値が得られます –

1

これは、「追加」変数が実際にはpush_var変数への参照であるためです。したがって、キューにプッシュすると、変数への参照がプッシュされます。 "add + 0"を押すと、プッシュ時に "add + 0"の値を含む新しいテンソルをプッシュしていることを意味します。これがその理由です。

+0

ありがとう。あなたはこれを正しく達成する方法を知っていますか? – hetelek

+1

ええ、私は正しい方法が何であるか分かりませんが、これを達成するための方法の1つは、tmp = tf.add(push_var、1)(新しいテンソルを返します)を使用し、tmpをキューにプッシュし、 push_var = tf.assign(tmp)を実行します。 –

関連する問題