2016-08-26 13 views
11

Tensorflowはscatter_update()を提供し、0次元のテンソルのスライスに値を割り当てます。例えば、テンソルTが3次元である場合、値v[1,:,:]T[i,:,:]に割り当てることができます。 Tensorflowでスライス割り当てを行う方法

a = tf.Variable(tf.zeros([10,36,36])) 
value = np.ones([1,36,36]) 
d = tf.scatter_update(a,[0],value) 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    print a.eval() 
    sess.run(d) 
    print a.eval() 

しかし、どのような値に T[i,j,:]から v[1,1,:]を割り当てるには?

a = tf.Variable(tf.zeros([10,36,36])) 
value1 = np.random.randn(1,1,36)  
e = tf.scatter_update(a,[0],value1) #Error 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    print a.eval() 
    sess.rum(e) 
    print a.eval() 

TFが提供する他の機能やこれを行う簡単な方法はありますか?

答えて

6

は、ticket #206で議論されています。 まだ利用できません。

更新:これが実装されました。あなたのようなあなたが更新する所望の値に沿って変更したくない値を含む目的の行のブロックを構築することができ、利用可能であるassign_slice_update(または​​)までhttps://stackoverflow.com/a/43139565/6531137


:jdehesaの回答を参照してください。したがって:

import tensorflow as tf 

a = tf.Variable(tf.ones([10,36,36])) 

i = 3 
j = 5 

# Gather values inside the a[i,...] block that are not on column j 
idx_before = tf.concat(1, [tf.reshape(tf.tile(tf.Variable([i]), [j]), [-1, 1]), tf.reshape(tf.range(j), [-1, 1])]) 
values_before = tf.gather_nd(a, idx_before) 
idx_after = tf.concat(1, [tf.reshape(tf.tile(tf.Variable([i]), [36-j-1]), [-1, 1]), tf.reshape(tf.range(j+1, 36), [-1, 1])]) 
values_after = tf.gather_nd(a, idx_after) 

# Build a subset of tensor `a` with the values that should not be touched and the values to update 
block = tf.concat(0, [values_before, 5*tf.ones([1, 36]), values_after]) 

d = tf.scatter_update(a, i, block) 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    sess.run(d) 
    print(a.eval()[3,4:7,:]) # Print a subset of the tensor to verify 

この例では、1のテンソルを生成し、a[i,j,:] = 5を実行します。複雑さの大部分は、変更したくない値を取得することにあります。a[i,~j,:](そうでない場合はscatter_update()がそれらの値を置き換えます)。

質問したとおりにT[i,k,:] = a[1,1,:]を実行する場合は、前の例の5*tf.ones([1, 36])tf.gather_nd(a, [[1, 1]])に置き換える必要があります。

別のアプローチは、それからtf.select()所望の要素にマスクを作成し、そのようなものとして、バック変数に代入することであろう。

import tensorflow as tf 

a = tf.Variable(tf.zeros([10,36,36])) 

i = tf.Variable([3]) 
j = tf.Variable([5]) 

# Build a mask using indices to perform [i,j,:] 
atleast_2d = lambda x: tf.reshape(x, [-1, 1]) 
indices = tf.concat(1, [atleast_2d(tf.tile(i, [36])), atleast_2d(tf.tile(j, [36])), atleast_2d(tf.range(36))]) 
mask = tf.cast(tf.sparse_to_dense(indices, [10, 36, 36], 1), tf.bool) 

to_update = 5*tf.ones_like(a) 
out = a.assign(tf.select(mask, to_update, a)) 

with tf.Session() as sess: 
    sess.run(tf.initialize_all_variables()) 
    sess.run(out) 
    print(a.eval()[2:5,5,:]) 

それが二回必要とするので、これは潜在的にあまり効率的なメモリの点ですと同じようにto_updateの変数を扱うメモリがありますが、この最後の例を簡単に変更して、tf.select(...)ノードからグラディエント保存操作を得ることができます。また、この他のStackOverflowに関する質問に興味があるかもしれません:Conditional assignment of tensor values in TensorFlow

これらのエレガントでない曲げは、使用可能になると、適切なTensorFlow関数への呼び出しに置き換えてください。

+0

詳細な例をありがとうございます!あなたが言ったように、現在のやり方はやや控えめです。すぐに 'assign_slice_update'関数が利用できることを願っています。 – user270700

+0

tf.selectがテンソルフロー1のtf.whereに置き換えられました。 –

14

現在、TensorFlowで変数のスライス割り当てを行うことができます。そこには特定の名前付き関数はありませんが、あなたは、スライスを選択し、その上にassignを呼び出すことができます。これはグラフのみに割り当てオペアンプを追加すること、しかし、

slice_assign = my_var[4:8].assign(tf.zeros(4)) 

ますが、それがない限り、それを実行されません他の操作の依存関係として明示的に実行または設定されます。良い習慣はtf.control_dependenciesコンテキストでそれを使用することです:

with tf.control_dependencies([my_var[4:8].assign(tf.zeros(4))]): 
    my_var = tf.identity(my_var) 

あなたはTensorFlow問題#4638でそれについての詳細を読むことができます(私は例をコピーした場所から)。

+1

これが受け入れられる回答になるはずです。 – user1735003

関連する問題