Использование tf.unpack(), когда первый размер переменной - None

Я питаюсь динамическим тензором, используя:

x = tf.placeholder(tf.int32, shape=[None, vector_size])

Мне нужно превратить это в список тензоров, у которых shape=[1, vector_size] используется x_list = tf.unpack(x, 0)

Но он вызывает ValueError, потому что длина первого измерения неизвестна, т.е. None.

Я пытался обойти это, используя другой tf.placeholder для динамического предоставления формы x, но параметр shape не может быть тензором.

Как я могу использовать tf.unpack() в этой ситуации?

Или есть еще одна функция, которая также может превратить переменную, которую я ввожу, в список тензоров?

Спасибо заранее.

Ответ 1

Я не думаю, что вы можете unpack тензор с аргументом num неуказанным и неизученным. Как сообщает документация:

Повышает ValueError, если num не указано и не может быть выведено.

Это как-то связано с тем, как внутренний дизайн TensorFlow для операций типа unpack. В этом другом протекторах Ярослав Булатов объяснил

Операции, такие как unpack, компилируются в операторы "тензор-в/тензор-выход" во время построения графика.

Следовательно, TensorFlow должен знать конкретное значение num для компиляции.

Хотя, я бы попытался обойти это, используя TensorArray. (см. следующий код для иллюстрации).

import tensorflow as tf
import numpy as np
sess = tf.InteractiveSession()
# assume vector_size=2 for simplicity
x = tf.placeholder(tf.int32, shape=[None, 2])
TensorArr = tf.TensorArray(tf.int32, 1, dynamic_size=True, infer_shape=False)
x_array = TensorArr.unpack(x)

TensorArray - это класс для переноса массивов динамического размера тензоров. При инициализации объекта TensorArray в этом приложении TensorArr = tf.TensorArray(tf.int32, 1, dynamic_size=True, infer_shape=False) установите dynamic_size=True и infer_shape=False, поскольку форма заполнителя x определяется только частично.

Чтобы получить доступ к каждому распакованному элементу:

# access the first element
x_elem0 = x_array.read(0)
# access the last element
last_idx = tf.placeholder(tf.int32)
x_last_elem = x_array.read(last_idx)

Затем во время оценки:

# generate random numpy array
dim0 = 4
x_np = np.random.randint(0, 25, size=[dim0, 2])
print x_np
# output of print x_np
[[17 15] 
[17 19]
[ 3  0]
[ 4 13]]

feed_dict = {x : x_np, last_idx : dim0-1} #python 0 based indexing
x_elem0.eval(feed_dict=feed_dict)
array([17, 15], dtype=int32) #output of x_elem0.eval(feed_dict)

x_last_elem.eval(feed_dict=feed_dict)
array([ 4, 13], dtype=int32) #output of x_last_elem.eval(feed_dict)
sess.close()

Обратите внимание, что при попытке получить доступ к каждому распакованному элементу, если значение index отсутствует, вы сможете передать компиляцию, но во время выполнения вы получите сообщение об ошибке, указывающее, что индекс не связан. Кроме того, форма распакованного тензора будет TensorShape(None), так как форма x определяется лишь частично до оценки.

Ответ 2

Вероятно, tf.dynamic_partition может помочь, но для этого требуется статическое число выходных тензоров. Если вы можете установить максимальное количество тензоров, вы можете использовать его.

import tensorflow as tf
import numpy as np

x = tf.placeholder(tf.int32, shape=[None, 2])
data = np.random.randint(10, size=(10,2))

parts = range(len(data))
out = tf.dynamic_partition(x, parts, 20)

sess = tf.Session()
print 'out tensors:\n', out
print
print 'input data:\n', data
print
print 'sess.run result:\n', sess.run(out, {x: data})

Выводит следующее:

out tensors:
[<tf.Tensor 'DynamicPartition:0' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:1' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:2' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:3' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:4' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:5' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:6' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:7' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:8' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:9' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:10' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:11' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:12' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:13' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:14' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:15' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:16' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:17' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:18' shape=(?, 2) dtype=int32>,
 <tf.Tensor 'DynamicPartition:19' shape=(?, 2) dtype=int32>]
input data:
[[7 6]
 [5 1]
 [4 6]
 [4 8]
 [4 9]
 [0 9]
 [9 6]
 [7 6]
 [0 5]
 [9 7]]

sess.run result:
[array([[7, 3]], dtype=int32),
 array([[0, 5]], dtype=int32),
 array([[2, 3]], dtype=int32),
 array([[2, 6]], dtype=int32),
 array([[7, 9]], dtype=int32),
 array([[8, 2]], dtype=int32),
 array([[1, 5]], dtype=int32),
 array([[3, 7]], dtype=int32),
 array([[6, 7]], dtype=int32),
 array([[8, 1]], dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32),
 array([], shape=(0, 2), dtype=int32)]