web-dev-qa-db-fra.com

Emettre une liste dans feed_dict dans TensorFlow

J'essaie de passer une liste dans feed_dict, mais j'ai du mal à le faire. Dis que j'ai:

inputs = 10 * [tf.placeholder(tf.float32, shape=(batch_size, input_size))]

où les entrées sont introduites dans une fonction outputs que je veux calculer. Donc, pour l'exécuter dans tensorflow, j'ai créé une session et exécuté:

sess.run(outputs, feed_dict = {inputs: data}) 
#data is my list of inputs, which is also of length 10

mais je reçois une erreur, TypeError: unhashable type: 'list'. Cependant, je suis capable de transmettre les données élémentaires comme ceci:

sess.run(outputs, feed_dict = {inputs[0]: data[0], ..., inputs[9]: data[9]}) 

Je me demande donc s'il est possible de résoudre ce problème. J'ai aussi essayé de construire un dictionnaire (en utilisant une boucle for), mais cela donne un dictionnaire avec un seul élément, où la clé est: tensorflow.python.framework.ops.Tensor at 0x107594a10

23
d-roy

Il y a deux problèmes qui causent des problèmes ici:

Le premier problème est que l'appel Session.run() n'accepte qu'un petit nombre de types en tant que clés du feed_dict. En particulier, les listes de tenseurs sont non prises en charge en tant que clés. Vous devez donc définir chaque tenseur en tant que clé distincte.* Pour cela, utilisez un dictionnaire comprenant:

inputs = [tf.placeholder(...), ...]
data = [np.array(...), ...]
sess.run(y, feed_dict={i: d for i, d in Zip(inputs, data)})

Le deuxième problème est que la syntaxe 10 * [tf.placeholder(...)] dans Python crée une liste de dix éléments, chaque élément étant le même objet tenseur (c'est-à-dire qu'il a la même propriété name, la même propriété id et est reference-identique si vous comparez deux éléments de la liste avec inputs[i] is inputs[j]). Cela explique pourquoi, lorsque vous avez essayé de créer un dictionnaire en utilisant les éléments de la liste comme clés, vous vous êtes retrouvé avec un dictionnaire avec un seul élément, car tous les éléments de la liste étaient identiques.

Pour créer 10 tenseurs d'espace réservé différents, comme vous le souhaitiez, procédez comme suit:

inputs = [tf.placeholder(tf.float32, shape=(batch_size, input_size))
          for _ in xrange(10)]

Si vous imprimez les éléments de cette liste, vous verrez que chaque élément est un tenseur portant un nom différent.


MODIFIER: * Vous pouvez maintenant passer tuples en tant que clés d'un feed_dict, car ils peuvent être utilisés en tant que clés de dictionnaire.

41
mrry

Voici un exemple correct:

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

Et voici une chose étrange que je vois dans votre approche. Pour une raison quelconque, vous utilisez 10 * [tf.placeholder(...)], qui crée 10 tenseurs de taille (batch_size, input_size). Vous ne savez pas pourquoi vous faites cela si vous pouvez créer simplement sur un tenseur de rang 3 (où la première dimension est 10).

Parce que vous avez une liste de tenseurs (et non un tenseur), vous ne pouvez pas alimenter vos données avec cette liste (mais dans mon cas, je peux nourrir mon tenseur). 

4
Salvador Dali

feed_dict peut être fourni en préparant un dictionnaire à l'avance comme suit

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)
0
tansg