Подтвердить что ты не робот

LSTM Autoencoder

Я пытаюсь создать автообнаружение LSTM с целью получения фиксированного размера вектора из последовательности, которая представляет последовательность как можно лучше. Этот автококкер состоит из двух частей:

  • LSTM Encoder: принимает последовательность и возвращает выходной вектор (return_sequences = False)
  • LSTM Декодер: принимает выходной вектор и возвращает последовательность (return_sequences = True)

Итак, в конце концов, кодер - это много к одному LSTM, а декодер - это один для многих LSTM.

введите описание изображения здесь

На высоком уровне кодировка выглядит так (как описано здесь):

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)

Форма (количество примеров обучения, длина последовательности, размер ввода) массива data составляет (1200, 10, 5) и выглядит следующим образом:

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]],
        ... ]

Проблема: Я не уверен, как действовать, особенно, как интегрировать LSTM в Model и как заставить декодер генерировать последовательность из вектора.

Я использую keras с бэкэндом tensorflow.

EDIT: Если кто-то хочет попробовать, вот моя процедура для генерации случайных последовательностей с движущимися (включая дополнение):

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.
)
4b9b3361

Ответ 1

Модели могут быть любыми способами. Если бы я понял это правильно, вы просто хотите знать, как создавать модели с LSTM?

Использование LSTM

Ну, во-первых, вы должны определить, как выглядит ваш кодированный вектор. Предположим, вы хотите, чтобы это был массив из 20 элементов, одномерный вектор. Итак, форма (нет, 20). Размер его зависит от вас, и нет четкого правила знать идеальный.

И ваш вход должен быть трехмерным, например, вашим (1200,10,5). В сводках keras и сообщениях об ошибках он будет показан как (None, 10,5), так как "None" представляет размер партии, который может меняться каждый раз, когда вы тренируетесь/прогнозируете.

Существует много способов сделать это, но предположим, что вам нужен только один слой 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)

Этого достаточно для очень простого кодировщика, приводящего к массиву с 20 элементами (но вы можете собрать больше слоев, если хотите). Позвольте создать модель:

encoder = Model(inpE,outE)   

Теперь, для декодера, он становится неясным. У вас больше нет фактической последовательности, а статический значимый вектор. Возможно, вы захотите использовать LTSM, они предполагают, что вектор является последовательностью.

Но здесь, поскольку вход имеет форму (None, 20), вы должны сначала изменить его на какой-то 3-мерный массив, чтобы добавить следующий слой LSTM.

То, как вы измените его, полностью зависит от вас. 20 шагов по 1 элементу? 1 шаг из 20 элементов? 10 шагов из 2 элементов? Кто знает?

inpD = Input((20,))   
outD = Reshape((10,2))(inpD) #supposing 10 steps of 2 elements    

Важно заметить, что если у вас больше нет 10 шагов, вы не сможете просто включить "return_sequences" и получить нужный результат. Вам придется немного поработать. На самом деле, нет необходимости использовать "return_sequences" или даже использовать LSTM, но вы можете это сделать.

Так как в моем изменении у меня есть 10 временных меток (намеренно), будет нормально использовать "return_sequences" , потому что результат будет иметь 10 временных меток (в качестве начального ввода)

outD1 = LSTM(5,return_sequences=True,...optional parameters...)(outD)    
#5 cells because we want a (None,10,5) vector.   

Вы могли бы работать многими другими способами, например, просто создать 50-элементный LSTM без возвращаемых последовательностей и затем изменить результат:

alternativeOut = LSTM(50,return_sequences=False,...)(outD)    
alternativeOut = Reshape((10,5))(alternativeOut)

И наша модель идет:

decoder = Model(inpD,outD1)  
alternativeDecoder = Model(inpD,alternativeOut)   

После этого вы объединяете модели с кодом и тренируете автокодер. Все три модели будут иметь одинаковые веса, поэтому вы можете заставить кодер привести результаты, используя метод predict.

encoderPredictions = encoder.predict(data)

То, что я часто вижу о LSTM для генерации последовательностей, похоже на предсказание следующего элемента.

Вы берете только несколько элементов последовательности и пытаетесь найти следующий элемент. И вы делаете другой сегмент на один шаг вперед и так далее. Это может быть полезно при генерации последовательностей.