Автоэнкодер LSTM на таймсериях


В настоящее время я пытаюсь реализовать автоэнкодер LSTM, который будет использоваться для сжатия временных рядов транзакций (набор данных Berka) в меньший кодированный вектор. Данные, с которыми я работаю, выглядят так: это (это совокупный баланс одного счета в течение всего времени).

Я решил использовать Keras, и я попытался создать простой автоэнкодер, следуя этому учебнику. Модель не работает.

Мой код таков:

import keras
from keras import Input, Model
from keras.layers import Lambda, LSTM, RepeatVector
from matplotlib import pyplot as plt
from scipy import io
from sklearn.preprocessing import MinMaxScaler
import numpy as np

class ResultPlotter(keras.callbacks.Callback):
    def on_epoch_end(self, epoch, logs={}):
        plt.subplots(2, 2, figsize=(10, 3))
        indexes = np.random.randint(datapoints, size=4)
        for i in range(4):
            plt.subplot(2, 2, i+1)
            plt.plot(sparse_balances[indexes[i]])
            result = sequence_autoencoder.predict(sparse_balances[0:1])
            plt.plot(result.T)
            plt.xticks([])
            plt.yticks([])
        plt.tight_layout()
        plt.show()
        return

result_plotter = ResultPlotter()

sparse_balances = io.mmread("my_path_to_sparse_balances.mtx")
sparse_balances = sparse_balances.todense()
scaler = MinMaxScaler(feature_range=(0, 1))
sparse_balances = scaler.fit_transform(sparse_balances)

N = sparse_balances.shape[0]
D = sparse_balances.shape[1]


batch_num = 32
timesteps = 500
latent_dim = 32
datapoints = N

model_inputs = Input(shape=(timesteps,))
inputs = Lambda(lambda x: keras.backend.expand_dims(x, -1))(model_inputs)
encoded = LSTM(latent_dim)(inputs)
decoded = RepeatVector(timesteps)(encoded)
decoded = LSTM(1, return_sequences=True)(decoded)
decoded = Lambda(lambda x: keras.backend.squeeze(x, -1))(decoded)
sequence_autoencoder = Model(model_inputs, decoded)
encoder = Model(model_inputs, encoded)

earlyStopping = keras.callbacks.EarlyStopping(monitor='loss', patience=5, verbose=0, mode='auto')

sequence_autoencoder.compile(loss='mean_squared_error', optimizer='adam')

sequence_autoencoder.fit(sparse_balances[:datapoints], sparse_balances[:datapoints],
                         batch_size=batch_num, epochs=100,
                        callbacks=[earlyStopping, result_plotter])

Я не добавляю код для генерации sparse_balanced.mtx для того, чтобы все было ясно, не стесняйтесь просить об этом, и я опубликую его.

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

Тогда возникает вопрос: учитывая тот факт, что с помощью LSTM->плотных или плотных->плотных автоэнкодеров я могу получить достойные результаты, а использование плотных->LSTM и LSTM->LSTM приводит к одинаковым плохим прогнозам, является ли проблема в моей модели, в концепции или в другом месте?

Каждый комментарий очень ценится, спасибо.

1 4

1 ответ:

Проблема заключалась в том, что мой набор данных слишком узок, чтобы его можно было легко автоматически закодировать с помощью LSTMs. В настоящее время я пишу магистерскую диссертацию на тему генерации транзакций, и я подробно проанализировал эту проблему. Если вы не работаете с этим набором данных в частности, я предлагаю попробовать с некоторыми синтетическими данными, связанными с временем, такими как синусоидальные волны, пилообразные волны и т. д. так как модель должна уметь правильно работать над этим. Если он все еще не работает, вероятно, у вас есть некоторые ошибки в коде.