2016-08-26 24 views
11

Tensorflow'un 0 boyutunda bir tensör dilimine değer atamak için scatter_update() sağladığını buldum. Örneğin, tensör T üç boyut ise, v[1,:,:] değerini T[i,:,:]'a atayabilirim. Tensorflow'da dilim ataması nasıl yapılır

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() 

Ama nasıl değer T[i,j,:] için v[1,1,:] atamak?

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'nin sağladığı başka bir işlev var mı, yoksa bunu yapmanın basit bir yolu var mı?

cevap

6

İhtiyacınız olan şeyin, ticket #206 numaralı makalede anlatılan assign_slice_update olduğuna inanıyorum. Henüz mevcut değil.

GÜNCELLEME: Bu şimdi uygulanmaktadır. gibi assign_slice_update (veya scatter_nd()) elde edilene kadar https://stackoverflow.com/a/43139565/6531137


, size güncellemek için istenen değerlerle birlikte değiştirmek istemiyorum değerleri içeren istenen satırın bir blok inşa edebileceğini: jdehesa cevabını bakın böylece:

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 

örnek olanlar bir tensörünün oluşturmak ve a[i,j,:] = 5 gerçekleştirir. Karmaşıklığın çoğu, değiştirmek istemediğimiz değerleri almak için yatıyor, a[i,~j,:] (aksi takdirde scatter_update() bu değerleri değiştirecektir). Eğer istediğin gibi T[i,k,:] = a[1,1,:] gerçekleştirmek istiyorsanız

, sen tf.gather_nd(a, [[1, 1]]) tarafından önceki örnekte 5*tf.ones([1, 36]) değiştirmeniz gerekiyor.

Bir başka yaklaşım gibi tf.select() etmek üzere bundan istenilen eleman bir maske oluşturmak ve değişken geri atamak olacaktır:

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,:]) 

Bu potansiyel olarak daha az etkin bir bellek açısından olan iki kez gerektirdiği a benzeri to_update değişkenini işlemek için bellek, ancak tf.select(...) düğümünden bir degrade koruma işlemi almak için bu son örneği kolayca değiştirebilirsiniz. Bu diğer StackOverflow sorusuna da bakmak ilginizi çekebilir: Conditional assignment of tensor values in TensorFlow.

Bu belirsiz çarpıklıklar, uygun TensorFlow işlevinin kullanılabilir hale geldiği bir çağrıya değiştirilmelidir.

+0

Detaylı örnek için teşekkürler! Dediğin gibi, şu anki yol biraz yetersiz. Umarım 'assign_slice_update' işlevi yakında kullanıma hazırdır. – user270700

+0

tf.select, tens.de 1'de tf.where ile değiştirilmiştir. –

14

Şu anda TensorFlow'daki değişkenler için dilim ataması yapabilirsiniz. Orada onun için hiçbir spesifik adlandırılmış işlev ama bir dilim seçin ve üzerinde assign arayabilirsiniz: Bu sadece grafiğe atama op katacak Ancak

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

Not, ama bunun sürece bunu yayınlanmaz Açıkça yürütülür veya başka bir işlemin bağımlılığı olarak ayarlanır. İyi bir uygulama, bir tf.control_dependencies bağlam içinde kullanmaktır:

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

Sen TensorFlow sayısında #4638 bu konuda daha fazla bilgi bulabilirsiniz (I örnekler kopyalanan yerden).

+1

Bu şimdi kabul edilen yanıt olmalıdır. – user1735003