34 votes

Comment utiliser l'option return_sequences et la couche TimeDistributed dans Keras ?

J'ai un corpus de dialogue comme ci-dessous. Et je veux implémenter un modèle LSTM qui prédit une action du système. L'action du système est décrite comme un vecteur de bits. L'entrée de l'utilisateur est calculée comme un encodage de mots qui est également un vecteur de bits.

t1: user: "Do you know an apple?", system: "no"(action=2)
t2: user: "xxxxxx", system: "yyyy" (action=0)
t3: user: "aaaaaa", system: "bbbb" (action=5)

Ce que je veux réaliser, c'est un modèle "many to many (2)". Lorsque mon modèle reçoit une entrée de l'utilisateur, il doit produire une action du système. enter image description here Mais je ne peux pas comprendre return_sequences et l'option TimeDistributed après la couche LSTM. Pour réaliser le "many-to-many (2)", return_sequences==True et l'ajout d'un TimeDistributed après que les LSTM sont nécessaires ? J'apprécierais que vous fournissiez une description plus détaillée.

séquences_de_retour : Booléen. Indique s'il faut renvoyer la dernière sortie de la séquence de sorties ou la séquence complète.

Temps distribué : Ce wrapper permet d'appliquer une couche à chaque tranche temporelle d'une entrée.

Mise à jour 2017/03/13 17:40

Je pense que je pourrais comprendre la return_sequence option. Mais je ne suis pas encore sûr TimeDistributed . Si j'ajoute un TimeDistributed après LSTMs, le modèle est-il le même que "my many-to-many(2)" ci-dessous ? Je pense donc que des couches denses sont appliquées pour chaque sortie. enter image description here

41voto

Nassim Ben Points 6973

La couche LSTM et l'enveloppe TimeDistributed sont deux façons différentes d'obtenir la relation "plusieurs à plusieurs" que vous souhaitez.

  1. La LSTM va manger les mots de votre phrase un par un, vous pouvez choisir via "return_sequence" de sortir quelque chose (l'état) à chaque étape (après chaque mot traité) ou de ne sortir quelque chose qu'après que le dernier mot ait été mangé. Ainsi, avec return_sequence=TRUE, la sortie sera une séquence de la même longueur, avec return_sequence=FALSE, la sortie sera juste un vecteur.
  2. Temps distribué. Cette enveloppe vous permet d'appliquer une couche (Dense par exemple) à chaque élément de votre séquence. de manière indépendante . Cette couche aura exactement les mêmes poids pour chaque élément, c'est la même qui sera appliquée à chaque mot et elle renverra, bien sûr, la séquence des mots traités indépendamment.

Comme vous pouvez le voir, la différence entre les deux est que la LSTM "propage l'information à travers la séquence, elle mangera un mot, mettra à jour son état et le renverra ou non. Ensuite, il passera au mot suivant tout en continuant à transporter l'information des mots précédents.... comme dans le TimeDistributed, les mots seront traités de la même manière, comme s'ils étaient dans des silos et que la même couche s'appliquait à chacun d'entre eux.

Vous n'êtes donc pas obligé d'utiliser LSTM et TimeDistributed à la suite, vous pouvez faire ce que vous voulez, mais gardez à l'esprit ce que fait chacun d'entre eux.

J'espère que c'est plus clair ?

EDIT :

Le temps distribué, dans votre cas, applique une couche dense à chaque élément produit par la LSTM.

Prenons un exemple :

Vous avez une séquence de n_mots qui sont intégrés dans des dimensions emb_size. Votre entrée est donc un tenseur 2D de forme (n_words, emb_size)

Vous appliquez d'abord une LSTM avec une dimension de sortie = lstm_output y return_sequence = True . La sortie sera toujours une séquence, donc un tenseur 2D de forme. (n_words, lstm_output) . Vous avez donc n_mots vecteurs de longueur lstm_output.

Vous appliquez maintenant une couche dense TimeDistributed avec, par exemple, une sortie en 3 dimensions comme paramètre de la couche dense. Donc TimeDistributed(Dense(3)). Cela appliquera Dense(3) n_mots fois, à chaque vecteur de taille lstm_output dans votre séquence indépendamment... ils deviendront tous des vecteurs de longueur 3. Votre sortie sera toujours une séquence, donc un tenseur 2D, de forme maintenant (n_words, 3) .

Est-ce plus clair ? :-)

5voto

naaviii Points 122
    return_sequences=True parameter:

Si nous voulons obtenir une séquence en sortie, et non un simple vecteur comme dans le cas des réseaux neuronaux normaux, il est nécessaire de définir la valeur True pour le paramètre return_sequences. Concrètement, disons que nous avons une entrée de forme (num_seq, seq_len, num_feature). Si nous ne définissons pas return_sequences=True, notre sortie aura la forme (num_seq, num_feature), mais si nous le faisons, nous obtiendrons la sortie avec la forme (num_seq, seq_len, num_feature).

    TimeDistributed wrapper layer:

Comme nous avons défini return_sequences=True dans les couches LSTM, la sortie est maintenant un vecteur tridimensionnel. Si nous entrons ce vecteur dans la couche Dense, une erreur se produira car la couche Dense n'accepte que des entrées bidimensionnelles. Pour saisir un vecteur tridimensionnel, nous devons utiliser une couche enveloppante appelée TimeDistributed. Cette couche nous aidera à maintenir la forme de la sortie, de sorte que nous puissions obtenir une séquence comme sortie à la fin.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X