web-dev-qa-db-ja.com

TensorFlowでopを割り当てます:戻り値は何ですか?

TensorFlowで自動インクリメントグラフを作成しようとしていました。 assign 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)

このコードは機能します。

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

推奨されない操作ですか?

9
Dims

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)
# ...
_
16
mrry

tf.assign()はうまく機能します 最新バージョンで文書化されています そしてそれはプロジェクトで頻繁に使用されます。

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

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

4
Salvador Dali