web-dev-qa-db-fra.com

Comment traiter des lots avec des séquences de longueur variable dans TensorFlow?

J'essayais d'utiliser un RNN (plus précisément, LSTM) pour la prédiction de séquence. Cependant, j'ai rencontré un problème avec des longueurs de séquence variables. Par exemple,

sent_1 = "I am flying to Dubain"
sent_2 = "I was traveling from US to Dubai"

J'essaie de prédire le prochain mot après l'actuel avec un simple RNN basé sur ce Indice de référence pour la construction d'un modèle PTB LSTM .

Cependant, le paramètre num_steps (utilisé pour le déroulement dans les états masqués précédents) devrait rester le même dans chaque époque Tensorflow. Fondamentalement, le groupement de phrases n’est pas possible car leur longueur varie. 

 # inputs = [tf.squeeze(input_, [1])
 #           for input_ in tf.split(1, num_steps, inputs)]
 # outputs, states = rnn.rnn(cell, inputs, initial_state=self._initial_state)

Ici, num_steps doit être changé dans mon cas pour chaque phrase. J'ai essayé plusieurs hacks, mais rien ne semble fonctionner.

18
Seja Nair

Vous pouvez utiliser les idées de seau et de remplissage décrites dans: 

Modèles séquence à séquence

De plus, la fonction rnn qui crée un réseau RNN accepte le paramètre sequence_length.

Par exemple, vous pouvez créer des compartiments de phrases de la même taille, les compléter avec la quantité nécessaire de zéros ou des espaces réservés représentant 0 mot et les alimenter avec seq_length = len (zero_words).

seq_length = tf.placeholder(tf.int32)
outputs, states = rnn.rnn(cell, inputs, initial_state=initial_state, sequence_length=seq_length)

sess = tf.Session()
feed = {
    seq_length: 20,
    #other feeds
}
sess.run(outputs, feed_dict=feed)

Jetez également un coup d'œil à ce fil reddit: 

Exemple RNN de base Tensorflow avec des séquences de «longueur variable»

18
Taras Sereda

Vous pouvez utiliser dynamic_rnn à la place et spécifier la longueur de chaque séquence, même au sein d'un lot, en passant un tableau au paramètre sequence_length . Exemple ci-dessous:

def length(sequence):
    used = tf.sign(tf.reduce_max(tf.abs(sequence), reduction_indices=2))
    length = tf.reduce_sum(used, reduction_indices=1)
    length = tf.cast(length, tf.int32)
    return length

from tensorflow.nn.rnn_cell import GRUCell

max_length = 100
frame_size = 64
num_hidden = 200

sequence = tf.placeholder(tf.float32, [None, max_length, frame_size])
output, state = tf.nn.dynamic_rnn(
    GRUCell(num_hidden),
    sequence,
    dtype=tf.float32,
    sequence_length=length(sequence),
)

Le code provient d'un article parfait sur le sujet, veuillez également le vérifier. 

Mise à jour: Un autre excellent article sur dynamic_rnn vs rnn vous pouvez trouver 

14
Datalker

Vous pouvez limiter la longueur maximale de vos séquences d'entrée, associer les plus courtes à cette longueur, enregistrer la longueur de chaque séquence et utiliser tf.nn.dynamic_rnn . Il traite les séquences d'entrée comme d'habitude, mais après le dernier élément d'une séquence, indiqué par seq_length, il ne fait que copier l'état de la cellule, et pour la sortie, il génère un zéro-tenseur.

4
tnq177

Vous pouvez utiliser les idées de seau et de remplissage décrites dans 

Modèles séquence à séquence

De plus, la fonction rnn qui crée un réseau RNN accepte le paramètre sequence_length.

À titre d’exemple, vous pouvez créer des groupes de peines de même taille, les ajouter avec le nombre de zéros nécessaire ou des espaces réservés représentant zéro mot, puis les alimenter avec seq_length = len (zero_words).

seq_length = tf.placeholder(tf.int32)
outputs, states = rnn.rnn(cell, inputs,initial_state=initial_state,sequence_length=seq_length)

sess = tf.Session()
feed = {
seq_lenght: 20,
#other feeds
       }
sess.run(outputs, feed_dict=feed)

Ici, le plus important est que, si vous voulez utiliser les états obtenus par une phrase comme, l'état de la phrase suivante, lorsque vous fournissez sequence_length, (disons 20 et phrase après le remplissage est 50). Vous voulez que l'état soit obtenu au 20ème pas de temps. Pour ça, fais

tf.pack(states)

Après cet appel 

for i in range(len(sentences)):
state_mat   = session.run([states],{
            m.input_data: x,m.targets: y,m.initial_state: state,     m.early_stop:early_stop })
state = state_mat[early_stop-1,:,:]
4
Seja Nair

Désolé de poster sur un problème mort, mais je viens de soumettre un PR pour une meilleure solution. dynamic_rnn est extrêmement flexible mais extrêmement lent. Cela fonctionne si c'est votre seule option mais CuDNN est beaucoup plus rapide. Ce PR ajoute le support pour les longueurs variables à CuDNNLSTM, vous pourrez donc l'utiliser bientôt.

Vous devez trier les séquences par longueur décroissante. Ensuite, vous pouvez pack_sequence, exécuter vos RNN, puis unpack_sequence.

https://github.com/tensorflow/tensorflow/pull/22308

1
Benjamin Striner