web-dev-qa-db-fra.com

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 système. L'action du système est décrite comme un vecteur de bits. Et une entrée utilisateur est calculée comme une intégration Word 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)

Donc, ce que je veux réaliser, c'est un modèle "plusieurs à plusieurs (2)". Lorsque mon modèle reçoit une entrée utilisateur, il doit générer une action système. enter image description here Mais je ne comprends pas return_sequences option et TimeDistributed couche après LSTM. Pour réaliser "plusieurs-à-plusieurs (2)", return_sequences==True et en ajoutant un TimeDistributed une fois les LSTM requis? Je vous serais reconnaissant de bien vouloir en décrire davantage.

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

TimeDistributed : Ce wrapper permet d'appliquer un calque à chaque tranche temporelle d'une entrée.

Mis à jour 2017/03/13 17:40

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

34
jef

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

  1. LSTM mangera 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 traitement de Word) ou de ne sortir quelque chose qu'une fois que le dernier mot a été mangé. Donc 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. TimeDistributed. Ce wrapper vous permet d'appliquer une couche (disons Dense par exemple) à chaque élément de votre séquence indépendamment. Cette couche aura exactement les mêmes poids pour chaque élément, c'est la même chose qui sera appliquée à chaque mot et elle renverra, bien sûr, la séquence de mots traitée indépendamment.

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

Vous n'avez donc pas à utiliser LSTM et TimeDistributed à la suite, vous pouvez faire ce que vous voulez, gardez à l'esprit ce que chacun d'eux fait.

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

MODIFIER:

Le temps distribué, dans votre cas, applique une couche dense à chaque élément qui a été émis par le LSTM.

Prenons un exemple:

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

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

Maintenant, vous appliquez une couche dense TimeDistributed avec, disons, une sortie en 3 dimensions comme paramètre de la densité. Donc TimeDistributed (Dense (3)). Ceci appliquera Dense (3) n_words fois, à tous les vecteurs 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? :-)

39
Nassim Ben
    return_sequences=True parameter:

Si nous voulons avoir une séquence pour la sortie, pas seulement un seul vecteur comme nous l'avons fait avec les réseaux neuronaux normaux, il est donc nécessaire de définir les return_sequences sur True. Concrètement, supposons que nous ayons 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:

Puisque nous définissons return_sequences = True dans les couches LSTM, la sortie est maintenant un vecteur à trois dimensions. Si nous saisissons cela dans la couche dense, cela générera une erreur car la couche dense n'accepte que des entrées bidimensionnelles. Pour entrer un vecteur en trois dimensions, nous devons utiliser une couche wrapper appelée TimeDistributed. Cette couche nous aidera à conserver la forme de la sortie, afin que nous puissions obtenir une séquence en sortie à la fin.

5
naaviii