Come utilizzare gli elenchi in tensorflow?
-
16-10-2019 - |
Domanda
Ho un certo numero di liste, come ad esempio [1,2,3,4], [2,3,4], [1,2], [2,3,4,6,8,10], le cui lunghezze sono ovviamente unsame.
Come posso utilizzare questo come input di segnaposto in tensorflow?
Come ho cercato, la seguente impostazione genererà errore.
tf.constant ([[1,2], [1,2,3] ...], DTYPE = tf.int32)
Quindi credo che segnaposto non può essere impostato per l'ingresso superiore delle liste.
C'è qualche soluzione?
Modifica :
Il seguente è il mio esempio. Come per farlo funzionare senza errori?
Soluzione
Quando si crea una matrice Numpy in questo modo:
x_data = np.array( [[1,2],[4,5,6],[1,2,3,4,5,6]])
Il DTYPE interna Numpy è "oggetto":
array([[1, 2], [4, 5, 6], [1, 2, 3, 4, 5, 6]], dtype=object)
e questo non può essere usato come un tensore in tensorflow. In ogni caso, devono avere Tensors stesse dimensioni in ogni dimensione, non possono essere "ragged" e deve avere una forma definita da un singolo numero in ciascuna dimensione. Tensorflow assume fondamentalmente questo su tutti i suoi tipi di dati. Anche se i progettisti di tensorflow potevano scriverlo in teoria rendere più accettare array laceri e comprendono una funzione di conversione, quel tipo di auto-casting non è sempre una buona idea, perché potrebbe nascondere un problema nel codice di ingresso.
Quindi è necessario per riempire i dati di input per renderla una forma utilizzabile. Su una rapida ricerca, ho trovato questo approccio in Stack Overflow , replicato come una modifica al codice:
import tensorflow as tf
import numpy as np
x = tf.placeholder( tf.int32, [3,None] )
y = x * 2
with tf.Session() as session:
x_data = np.array( [[1,2],[4,5,6],[1,2,3,4,5,6]] )
# Get lengths of each row of data
lens = np.array([len(x_data[i]) for i in range(len(x_data))])
# Mask of valid places in each row
mask = np.arange(lens.max()) < lens[:,None]
# Setup output array and put elements from data into masked positions
padded = np.zeros(mask.shape)
padded[mask] = np.hstack((x_data[:]))
# Call TensorFlow
result = session.run(y, feed_dict={x:padded})
# Remove the padding - the list function ensures we
# create same datatype as input. It is not necessary in the case
# where you are happy with a list of Numpy arrays instead
result_without_padding = np.array(
[list(result[i,0:lens[i]]) for i in range(lens.size)]
)
print( result_without_padding )
L'uscita è:
[[2, 4] [8, 10, 12] [2, 4, 6, 8, 10, 12]]
Non è necessario rimuovere l'imbottitura alla fine - farlo solo se si richiede di mostrare la vostra uscita nello stesso formato Jagged array. Si noti inoltre che quando si alimentano i dati risultanti padded
alle routine più complesse, gli zeri - o altri dati padding se si cambiano - può abituarsi con qualsiasi algoritmo è stato implementato
Se si dispone di molti array brevi e solo uno o due quelli molto lunghi, allora si potrebbe desiderare di considerare l'utilizzo di un sparse rappresentazione tensoriale per risparmiare memoria e accelerare i calcoli.
Altri suggerimenti
In alternativa l'utilizzo di matrici imbottite, si può solo nutrire tutti i dati come un unico grande stringa di spaghetti e poi fare origami all'interno del tensorflow grafico
Esempio:
import tensorflow as tf
import numpy as np
sess = tf.InteractiveSession()
noodle = tf.placeholder(tf.float32, [None])
chop_indices = tf.placeholder(tf.int32, [None,2])
do_origami = lambda list_idx: tf.gather(noodle, tf.range(chop_indices[list_idx,0], chop_indices[list_idx,1]))
print( [do_origami(list_idx=i).eval({noodle:[1,2,3,2,3,6], chop_indices:[[0,2],[2,3],[3,6]]}).tolist() for i in range(3)] )
Risultato:
[[1.0, 2.0], [3.0], [2.0, 3.0, 6.0]]
Se si dispone di un numero variabile di liste interne, però, quindi buona fortuna. Non si può restituire un elenco da tf.while_loop e non si può semplicemente utilizzare un elenco di comprensione come sopra in modo che avrebbe dovuto fare i calcoli separatamente per ciascuna lista interiore.
import tensorflow as tf
sess = tf.InteractiveSession()
my_list = tf.Variable(initial_value=[1,2,3,4,5])
init = tf.global_variables_initializer()
sess.run(init)
sess.run(my_list)
Risultato: array ([1, 2, 3, 4, 5])