J'essaie de construire un autoencodeur LSTM dans le but d'obtenir un vecteur de taille fixe à partir d'une séquence, qui représente la séquence aussi bien que possible. Cet autoencoder est composé de deux parties:
LSTM
Encoder: Prend une séquence et retourne un vecteur de sortie (return_sequences = False
)LSTM
Decoder: Prend un vecteur de sortie et retourne une séquence (return_sequences = True
)Donc, au final, le codeur est un plusieurs à un LSTM et le décodeur est un un à plusieurs LSTM.
Source de l'image: Andrej Karpathy
Sur un niveau élevé, le codage ressemble à ceci (semblable à celui décrit ici ):
encoder = Model(...)
decoder = Model(...)
autoencoder = Model(encoder.inputs, decoder(encoder(encoder.inputs)))
autoencoder.compile(loss='binary_crossentropy',
optimizer='adam',
metrics=['accuracy'])
autoencoder.fit(data, data,
batch_size=100,
epochs=1500)
La forme (nombre d'exemples d'apprentissage, longueur de séquence, dimension d'entrée) du tableau data
est (1200, 10, 5)
et ressemble à ceci:
array([[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
...,
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]],
... ]
Problème: Je ne sais pas comment procéder, en particulier comment intégrer LSTM
à Model
et comment obtenir le décodeur pour générer une séquence à partir d'un vecteur.
J'utilise keras
avec tensorflow
backend.
EDIT: Si quelqu'un veut essayer, voici ma procédure pour générer des séquences aléatoires avec celles qui bougent (y compris le remplissage):
import random
import math
def getNotSoRandomList(x):
rlen = 8
rlist = [0 for x in range(rlen)]
if x <= 7:
rlist[x] = 1
return rlist
sequence = [[getNotSoRandomList(x) for x in range(round(random.uniform(0, 10)))] for y in range(5000)]
### Padding afterwards
from keras.preprocessing import sequence as seq
data = seq.pad_sequences(
sequences = sequence,
padding='post',
maxlen=None,
truncating='post',
value=0.
)
Les modèles peuvent être comme vous le souhaitez. Si j'ai bien compris, vous voulez juste savoir comment créer des modèles avec LSTM?
tilisation de LSTM
Eh bien, vous devez d’abord définir à quoi ressemble votre vecteur codé. Supposons que vous souhaitiez un tableau de 20 éléments, un vecteur à une dimension. Donc, forme (Aucun, 20). La taille de celui-ci est à vous, et il n'y a pas de règle claire pour connaître l'idéal.
Et votre entrée doit être tridimensionnelle, telle que votre (1200,10,5). Dans les résumés de keras et les messages d'erreur, il sera indiqué par (Aucun, 10,5), car "Aucun" représente la taille du lot, qui peut varier à chaque fois que vous vous entraînez/prédisez.
Il y a plusieurs façons de le faire, mais supposons que vous ne vouliez qu'un seul calque LSTM:
from keras.layers import *
from keras.models import Model
inpE = Input((10,5)) #here, you don't define the batch size
outE = LSTM(units = 20, return_sequences=False, ...optional parameters...)(inpE)
Ceci est suffisant pour un encodeur très très simple résultant en un tableau de 20 éléments (mais vous pouvez empiler plus de couches si vous le souhaitez). Créons le modèle:
encoder = Model(inpE,outE)
Maintenant, pour le décodeur, cela devient obscur. Vous n'avez plus de séquence réelle, mais un vecteur significatif statique. Vous voudrez peut-être utiliser les LTSM quand même, ils vont supposer que le vecteur est une séquence.
Mais ici, étant donné que l’entrée a une forme (Aucune, 20), vous devez d’abord la remodeler en un tableau à 3 dimensions pour attacher ensuite un calque LSTM.
La façon dont vous allez le remodeler est entièrement à vous. 20 étapes de 1 élément? 1 étape de 20 éléments? 10 étapes de 2 éléments? Qui sait?
inpD = Input((20,))
outD = Reshape((10,2))(inpD) #supposing 10 steps of 2 elements
Il est important de noter que si vous n'avez plus 10 étapes, vous ne pourrez pas simplement activer "return_sequences" et obtenir le résultat souhaité. Vous devrez travailler un peu. En réalité, il n'est pas nécessaire d'utiliser "return_sequences" ni même d'utiliser les LSTM, mais vous pouvez le faire.
Puisque dans ma refonte, j'ai 10 timesteps (intentionnellement), il sera correct d'utiliser "return_sequences", car le résultat aura 10 timesteps (comme entrée initiale)
outD1 = LSTM(5,return_sequences=True,...optional parameters...)(outD)
#5 cells because we want a (None,10,5) vector.
Vous pouvez travailler de nombreuses autres manières, par exemple en créant simplement un LSTM à 50 cellules sans renvoyer de séquences, puis en remodelant le résultat:
alternativeOut = LSTM(50,return_sequences=False,...)(outD)
alternativeOut = Reshape((10,5))(alternativeOut)
Et notre modèle va:
decoder = Model(inpD,outD1)
alternativeDecoder = Model(inpD,alternativeOut)
Après cela, vous unissez les modèles avec votre code et formez le codeur automatique. Les trois modèles auront les mêmes poids, vous pouvez donc faire en sorte que l'encodeur obtienne des résultats en utilisant simplement sa méthode predict
.
encoderPredictions = encoder.predict(data)
Ce que je vois souvent à propos des LSTM pour générer des séquences est quelque chose comme une prédiction de l’élément suivant.
Vous ne prenez que quelques éléments de la séquence et essayez de trouver l'élément suivant. Et vous faites un autre pas en avant dans un autre segment, etc. Cela peut être utile pour générer des séquences.
Vous pouvez trouver une séquence simple de séquence autoencoder ici: https://blog.keras.io/building-autoencoders-in-keras.html