Проблема с подачей списка в feed_dict в TensorFlow
Я пытаюсь передать список в feed_dict
, однако у меня возникают проблемы с этим. Скажем, у меня есть:
inputs = 10 * [tf.placeholder(tf.float32, shape=(batch_size, input_size))]
где входы подаются в некоторую функцию outputs
, которую я хочу вычислить. Поэтому, чтобы запустить это в тензорном потоке, я создал сеанс и выполнил следующее:
sess.run(outputs, feed_dict = {inputs: data})
#data is my list of inputs, which is also of length 10
но я получаю сообщение об ошибке, TypeError: unhashable type: 'list'.
Тем не менее, я могу передать элемент данных таким образом:
sess.run(outputs, feed_dict = {inputs[0]: data[0], ..., inputs[9]: data[9]})
Итак, мне интересно, есть ли способ решить эту проблему. Я также попытался построить словарь (используя цикл for
), однако это приводит к созданию словаря с одним элементом, где они имеют следующий ключ:
tensorflow.python.framework.ops.Tensor at 0x107594a10
Ответы
Ответ 1
Здесь есть две проблемы:
Первая проблема заключается в том, что вызов Session.run()
принимает только небольшое количество типов в качестве ключей feed_dict
. В частности, списки тензоров не поддерживаются как ключи, поэтому вам нужно поместить каждый тензор в отдельный ключ. * Один из удобных способов сделать это - использование словаря
inputs = [tf.placeholder(...), ...]
data = [np.array(...), ...]
sess.run(y, feed_dict={i: d for i, d in zip(inputs, data)})
Вторая проблема заключается в том, что синтаксис 10 * [tf.placeholder(...)]
в Python создает список из десяти элементов, где каждый элемент тот же тензорный объект (т.е. имеет то же свойство name
, тот же id
, и является ссылочным, если вы сравниваете два элемента из списка, используя inputs[i] is inputs[j]
). Это объясняет, почему, когда вы пытались создать словарь, используя элементы списка в качестве ключей, вы получили словарь с одним элементом - потому что все элементы списка были идентичны.
Чтобы создать 10 различных тензодатчиков-заполнителей, как вы планировали, вы должны сделать следующее:
inputs = [tf.placeholder(tf.float32, shape=(batch_size, input_size))
for _ in xrange(10)]
Если вы напечатаете элементы этого списка, вы увидите, что каждый элемент представляет собой тензор с другим именем.
РЕДАКТИРОВАТЬ: * Теперь вы можете передать кортежи в качестве ключей feed_dict
, потому что они могут использоваться как словарные ключи.
Ответ 2
Вот правильный пример:
batch_size, input_size, n = 2, 3, 2
# in your case n = 10
x = tf.placeholder(tf.types.float32, shape=(n, batch_size, input_size))
y = tf.add(x, x)
data = np.random.rand(n, batch_size, input_size)
sess = tf.Session()
print sess.run(y, feed_dict={x: data})
И вот странные вещи, которые я вижу в вашем подходе. По какой-то причине вы используете 10 * [tf.placeholder(...)]
, который создает 10 тензоров размера (batch_size, input_size)
. Не знаю, зачем вы это делаете, если вы можете просто создать на тензоре 3-го ранга (где первое измерение равно 10).
Поскольку у вас есть список тензоров (а не тензор), вы не можете подавать свои данные в этот список (но в моем случае я могу подавать свой тензор).
Ответ 3
feed_dict может быть предоставлен путем предварительной подготовки словаря следующим образом
n = 10
input_1 = [tf.placeholder(...) for _ in range(n)]
input_2 = tf.placeholder(...)
data_1 = [np.array(...) for _ in range(n)]
data_2 = np.array(...)
feed_dictionary = {}
for i in range(n):
feed_dictionary[input_1[i]] = data_1[i]
feed_dictionary[input_2] = data_2
sess.run(y, feed_dict=feed_dictionary)