python - train - tensorflow raspberry pi
LSTM Autoencoder (2)
Puede encontrar una secuencia simple para secuenciar el autoencoder aquí: https://blog.keras.io/building-autoencoders-in-keras.html
Estoy intentando construir un autoencoder LSTM con el objetivo de obtener un vector de tamaño fijo a partir de una secuencia, lo que representa la secuencia lo mejor posible. Este autoencoder consta de dos partes:
- Encoder
LSTM
: toma una secuencia y devuelve un vector de salida (return_sequences = False
) - Decodificador
LSTM
: toma un vector de salida y devuelve una secuencia (return_sequences = True
)
Entonces, al final, el codificador es un LSTM de muchos a uno y el decodificador es uno a muchos LSTM.
En un nivel alto, la codificación se ve así (similar a la descrita aquí ):
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 forma (número de ejemplos de entrenamiento, longitud de la secuencia, dimensión de entrada) de la matriz de data
es (1200, 10, 5)
y se ve así:
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]],
... ]
Problema: no estoy seguro de cómo proceder, especialmente cómo integrar LSTM
al Model
y cómo hacer que el decodificador genere una secuencia a partir de un vector.
Estoy usando keras
con tensorflow
backend.
EDITAR: Si alguien quiere probar, aquí está mi procedimiento para generar secuencias aleatorias con las que se mueven (incluido el relleno):
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.
)
Los modelos pueden ser de cualquier forma que desee. Si lo entendí bien, ¿solo quieres saber cómo crear modelos con LSTM?
Usando LSTMs
Bueno, primero, tienes que definir cómo se ve tu vector codificado. Supongamos que quiere que sea una matriz de 20 elementos, un vector de 1 dimensión. Entonces, forma (Ninguno, 20). El tamaño depende de ti, y no hay una regla clara para saber cuál es la ideal.
Y su entrada debe ser tridimensional, como su (1200,10,5). En los resúmenes de keras y mensajes de error, se mostrará como (Ninguno, 10,5), ya que "Ninguno" representa el tamaño del lote, que puede variar cada vez que entrene / prediga.
Hay muchas formas de hacerlo, pero, supongamos que quiere una sola capa 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)
Esto es suficiente para un codificador muy simple que da como resultado una matriz con 20 elementos (pero puede apilar más capas si lo desea). Vamos a crear el modelo:
encoder = Model(inpE,outE)
Ahora, para el decodificador, se vuelve oscuro. Ya no tienes una secuencia real, sino un vector estático significativo. Es posible que desee utilizar LTSM aún, supondrán que el vector es una secuencia.
Pero aquí, dado que la entrada tiene forma (Ninguno, 20), primero debe darle nueva forma a una matriz tridimensional para adjuntar una capa LSTM a continuación.
La forma en que la remodelará depende totalmente de usted. 20 pasos de 1 elemento? 1 paso de 20 elementos? 10 pasos de 2 elementos? ¿Quién sabe?
inpD = Input((20,))
outD = Reshape((10,2))(inpD) #supposing 10 steps of 2 elements
Es importante notar que si ya no tienes 10 pasos, no podrás simplemente habilitar "return_sequences" y tener el resultado que deseas. Tendrás que trabajar un poco. De hecho, no es necesario usar "return_sequences" o incluso usar LSTM, pero puede hacerlo.
Como en mi remodelación tengo 10 pasos (intencionalmente), estará bien usar "return_sequences", porque el resultado tendrá 10 pasos (como entrada inicial)
outD1 = LSTM(5,return_sequences=True,...optional parameters...)(outD)
#5 cells because we want a (None,10,5) vector.
Podrías trabajar de muchas otras formas, como simplemente crear un LSTM de 50 celdas sin devolver secuencias y luego rediseñar el resultado:
alternativeOut = LSTM(50,return_sequences=False,...)(outD)
alternativeOut = Reshape((10,5))(alternativeOut)
Y nuestro modelo va:
decoder = Model(inpD,outD1)
alternativeDecoder = Model(inpD,alternativeOut)
Después de eso, unirás los modelos con tu código y entrenarás el autoencoder. Los tres modelos tendrán los mismos pesos, por lo que puede hacer que el codificador genere resultados simplemente usando su método de predict
.
encoderPredictions = encoder.predict(data)
Lo que a menudo veo sobre los LSTM para generar secuencias es algo así como predecir el próximo elemento.
Toma solo algunos elementos de la secuencia e intenta encontrar el siguiente elemento. Y tomas otro segmento un paso adelante y así sucesivamente. Esto puede ser útil para generar secuencias.