Нарезка тензорного потока на основе переменной
Я обнаружил, что индексирование по-прежнему является открытой проблемой в tensorflow (# 206), поэтому мне интересно, что я могу использовать в качестве обходного пути на данный момент, Я хочу индексировать/нарезать строку/столбец матрицы на основе переменной, которая изменяется для каждого примера обучения.
Что я пробовал до сих пор:
- Нарезка на основе заполнителя (не работает)
Следующие (рабочие) фрагменты кода на основе фиксированного числа.
import tensorflow as tf
import numpy as np
x = tf.placeholder("float")
y = tf.slice(x,[0],[1])
#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
#run
result = sess.run(y, feed_dict={x:[1,2,3,4,5]})
print(result)
Однако, похоже, я не могу просто заменить одно из этих фиксированных чисел на tf.placeholder. Следующий код дает мне ошибку "TypeError: список тензоров при ожидании одиночного тензора".
import tensorflow as tf
import numpy as np
x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,[i],[1])
#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
#run
result = sess.run(y, feed_dict={x:[1,2,3,4,5],i:0})
print(result)
Это звучит так, как скобки вокруг [i] слишком много, но удаление их тоже не помогает. Как использовать заполнитель/переменную в качестве индекса?
- Нарезка на основе переменной python (не поддерживает backprop/update должным образом)
Я также пытался использовать обычную переменную python в качестве индекса. Это не приводит к ошибке, но сеть не учит чему-либо во время обучения. Я полагаю, потому что изменяющаяся переменная неправильно зарегистрирована, график неверен и обновления не работают?
- Нарезка через одноструй вектор + умножение (работает, но медленнее)
Один обходной путь, который я нашел, - это использование горячего вектора. Создание одноразового вектора в numpy, передавая его с помощью заполнителя, а затем выполняем разбиение по матричному умножению. Это работает, но довольно медленно.
Любые идеи, как эффективно срезать/индексировать на основе переменной?
Ответы
Ответ 1
Нарезка, основанная на заполнителе, должна работать нормально. Похоже, вы сталкиваетесь с ошибкой типа из-за некоторых тонких проблем форм и типов. Где у вас есть следующее:
x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,[i],[1])
... вместо этого вы должны:
x = tf.placeholder("float")
i = tf.placeholder("int32")
y = tf.slice(x,i,[1])
... а затем вы должны отправить i
как [0]
в вызове sess.run()
.
Чтобы сделать это немного яснее, я бы рекомендовал переписать код следующим образом:
import tensorflow as tf
import numpy as np
x = tf.placeholder(tf.float32, shape=[None]) # 1-D tensor
i = tf.placeholder(tf.int32, shape=[1])
y = tf.slice(x, i, [1])
#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
#run
result = sess.run(y, feed_dict={x: [1, 2, 3, 4, 5], i: [0]})
print(result)
Дополнительные аргументы shape
для справки tf.placeholder
op, чтобы гарантировать, что значения, которые вы кормите, имеют соответствующие формы, а также то, что TensorFlow вызывает ошибку, если фигуры неправильны.
Ответ 2
Если у вас есть дополнительное измерение, это работает.
import tensorflow as tf
import numpy as np
def reorder0(e, i, length):
'''
e: a two dimensional tensor
i: a one dimensional int32 tensor, of shape (e.shape[0])
returns: a tensor of the same shape as e, where the jth entry is entry i[j] from e
'''
return tf.concat(
[ tf.expand_dims( e[i[j],:], axis=0) for j in range(length) ],
axis=0
)
e = tf.placeholder(tf.float32, shape=(2,3,5), name='e' ) # sentences, words, embedding
i = tf.placeholder(tf.int32, shape=(2,3), name='i' ) # for each word, index of parent
p = tf.concat(
[ tf.expand_dims(reorder0(e[k,:,:], i[k,:], 3), axis=0) for k in range(2) ],
axis=0,
name='p'
)
#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
#run
result = sess.run(p, feed_dict={
e: [
( (1.0,1.1,1.2,1.3,1.4),(2.0,2.1,2.2,2.3,2.4),(3.0,3.1,3.2,3.3,3.4) ),
( (21.0,21.1,21.2,21.3,21.4),(22.0,22.1,22.2,22.3,22.4),(23.0,23.1,23.2,23.3,23.4) ),
],
i: [ (1,1,1), (2,0,2)]
})
print(result)
Ответ 3
Если размеры не известны при построении модели, используйте TensorArray.
e = tf.placeholder(tf.float32, shape=(3,5) ) # words, embedding
i = tf.placeholder(tf.int32, shape=(3) ) # for each word, index of parent
#p = reorder0(e, i, 3)
a = tf.TensorArray(
tf.float32,
size=e.get_shape()[0],
dynamic_size=True,
infer_shape= True,
element_shape=e.get_shape()[1],
clear_after_read = False
)
#initialize
init = tf.initialize_all_variables()
sess = tf.Session()
sess.run(init)
#run
result = sess.run(
a.unstack(e).gather(i),
feed_dict={
e: ( (1.0,1.1,1.2,1.3,1.4),(2.0,2.1,2.2,2.3,2.4),(3.0,3.1,3.2,3.3,3.4) ),
#( (21.0,21.1,21.2,21.3,21.4),(22.0,22.1,22.2,22.3,22.4),(23.0,23.1,23.2,23.3,23.4) ),
i: (2,0,2)
}
)
print(result)