Wierzę, że to, czego potrzebujesz, to assign_slice_update
omówione w ticket #206. Nie jest jeszcze dostępna.
AKTUALIZACJA: To jest teraz zaimplementowane. Zobacz jdehesa za odpowiedź: https://stackoverflow.com/a/43139565/6531137
Do assign_slice_update
(lub scatter_nd()
) jest dostępny, można zbudować blok żądanego wiersza zawierającego wartości, których nie chcesz zmodyfikować wraz z pożądanymi wartościami zaktualizować, jak sposób:
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
Przykład generowania tensora jedynek i wykonuje a[i,j,:] = 5
. Większość złożoności polega na uzyskaniu wartości, których nie chcemy modyfikować, a[i,~j,:]
(w przeciwnym razie scatter_update()
zastąpi te wartości).
Jeśli chcesz wykonać polecenie T[i,k,:] = a[1,1,:]
na żądanie, musisz zastąpić 5*tf.ones([1, 36])
w poprzednim przykładzie przez tf.gather_nd(a, [[1, 1]])
.
Innym podejściem byłoby utworzenie maski tf.select()
odpowiednich elementów z nią i przypisać go do zmiennych, w następujący sposób:
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,:])
jest potencjalnie mniej skuteczne w zakresie pamięci od wymaga dwukrotnie pamięć do obsługi zmiennej a
-like to_update
, ale można łatwo zmodyfikować ten ostatni przykład, aby uzyskać operację zachowywania gradientu z węzła tf.select(...)
. Możesz być także zainteresowany patrząc na to inne pytanie StackOverflow: Conditional assignment of tensor values in TensorFlow.
Te nieeleganckie zakłócenia należy zastąpić wywołaniem odpowiedniej funkcji TensorFlow, gdy stanie się ona dostępna.
Dzięki za szczegółowy przykład! Jak powiedziałeś, obecny sposób jest nieco nieelegancki. Mam nadzieję, że funkcja 'assign_slice_update' będzie dostępna wkrótce. – user270700
tf.select został zastąpiony przez tf.where w tensorflow 1. –