2016-02-02 12 views
7

私はTensorFlowで自動インクリメントグラフを作成しようとしていました。私はassign opがそれに適しているかもしれないと思っていましたが、それについてのドキュメントは見つかりませんでした。TensorFlowでopを割り当てる:戻り値は何ですか?

私はこのOPは— — C-ような言語のようにその値を返し、次のコードを書いたと仮定:

import tensorflow as tf 

counter = tf.Variable(0, name="counter") 

one = tf.constant(1) 
ten = tf.constant(10) 

new_counter = tf.add(counter, one) 
assign = tf.assign(counter, new_counter) 
result = tf.add(assign, ten) 

init_op = tf.initialize_all_variables() 

with tf.Session() as sess: 

    sess.run(init_op) 

    for _ in range(3): 

    print sess.run(result) 

をし、このコードは動作します。

質問は、これは予想される動作ですか?代理opがここに記載されていないのはなぜですか:https://www.tensorflow.org/versions/0.6.0/api_docs/index.html

これは推奨されていませんか?

答えて

13

tf.assign()演算子は、Variable.assign()メソッドを実装する基本的なメカニズムです。 変更可能なテンソルtf.*_refタイプ)と新しい値を取り、変更可能なテンソルを新しい値で更新します。戻り値は、後続の読み込みの前に割り当てを順序付けするのを容易にするために提供されていますが、この機能は十分に文書化されていません。例では、うまくいけば説明します:あなたのコード例で

v = tf.Variable(0) 
new_v = v.assign(10) 
output = v + 5 # `v` is evaluated before or after the assignment. 

sess.run(v.initializer) 

result, _ = sess.run([output, new_v.op]) 
print result # ==> 10 or 15, depending on the order of execution. 

v = tf.Variable(0) 
new_v = v.assign(10) 
output = new_v + 5 # `new_v` is evaluated after the assignment. 

sess.run(v.initializer) 

result = sess.run([output]) 
print result # ==> 15 

をデータフローの依存関係がセマンティクスがあいまいでないことを意味し、実行[read counter] -> new_counter = tf.add(...) -> tf.assign(...) -> [read output of assign] -> result = tf.add(...)の順序を強制します。 ただし、複数のステップが同時に実行されている場合、カウンタを更新するための読み取り - 変更 - 書き込みステップはやや効率的ではなく、予期しない動作をする可能性があります。たとえば、同じ変数にアクセスする複数のスレッドは、逆方向に移動するカウンタを観察できます(古い値が新しい値の後に書き戻された場合)。

次のように私は、あなたがカウンターを更新するためにVariable.assign_add()を使用することをお勧めします:

counter = tf.Variable(0, name="counter") 

one = tf.constant(1) 
ten = tf.constant(10) 

# assign_add ensures that the counter always moves forward. 
updated_counter = counter.assign_add(one, use_locking=True) 

result = tf.add(updated_counter, ten) 
# ... 
+3

最初のコードスニペットを実行したところ、出力は5または15のいずれかにしかならないことがわかりました。 –

4

tf.assign()はうまくdocumented in the latest versionsあり、それは、プロジェクトで頻繁に使用されます。

この操作は、割り当てが完了した後に「ref」を出力します。これにより、 は、リセット値を使用する必要がある操作をより簡単に連鎖させることができます。

簡単な言葉では、元のテンソルと新しいテンソルが必要です。テンソルの元の値を新しい値で更新し、元のテンソルの参照を返します。

関連する問題