почему я получаю совершенно разные прогнозы от сети Keras LSTM в зависимости от порядка прогнозов? - PullRequest
0 голосов
/ 17 января 2020

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

1) Первая проблема заключается в том, что прогнозы на тесте и данные о поездах совершенно разные, в зависимости от того, предсказываю ли я сначала поезд или тест.

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

edit1: я пытался установить «stateful = False» как это было предложено в комментариях, но безуспешно.

edit2: я обновил скрипт и графики и предоставил некоторые базовые c синусоидальные образцы данных в новом коде. Проблемы все еще существуют даже в этом простом примере

результирующих графиков прогнозов с сохранением состояния = False

Я получил входной сигнал X в виде синусоиды с 100 временных шагов и случайная амплитуда и частота. Моя цель у соотносится с Х (на каждом временном шаге) и в этом случае также является синусоидой. Форма моих данных:

X_train.shape = (100, 1, 1)
y_train.shape = (100,)
X_test.shape = (100, 1, 1)
y_test.shape = (100,)

Я использую сеть LSTM, пытаясь согласовать полную синусоидальную волну, поэтому размер партии = 100, и прогнозирую каждую точку тестового сигнала, поэтому размер партии для предсказание = 1. Также я вручную сбрасываю состояние LSTM после каждой эпохи, как упомянуто здесь: https://machinelearningmastery.com/use-different-batch-sizes-training-predicting-python-keras/

Для построения своей сети я следовал «правилам keras» как упомянуто здесь: Задержка эха греха - не может воспроизвести результат Tensorflow в Keras

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

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

Спасибо вам всем! Вот мой пример кода:

import numpy as np
import matplotlib.pyplot as plt
from keras import models, layers, optimizers
from keras.callbacks import Callback


# create training sample data
Fs = 100  # sample rate
z = np.arange(100)
f = 1  # frequency in Hz
X_train = np.sin(2 * np.pi * f * z / Fs)
y_train = 0.1 * np.sin(2 * np.pi * f * z / Fs)


# create test sample data
f = 1  # frequency in Hz
X_test = np.sin(2 * np.pi * f * z / Fs) * 2
y_test = 0.2 * np.sin(2 * np.pi * f * z / Fs)


# convert data into LSTM compatible format
y_train = np.array(y_train)
y_test = np.array(y_test)
X_train = X_train.reshape(X_train.shape[0], 1, 1)
X_test = X_test.reshape(X_test.shape[0], 1, 1)


# build and compile model
model = models.Sequential()
model.add(layers.LSTM(1, batch_input_shape=(len(X_train), X_train.shape[1], X_train.shape[2]),
                      return_sequences=False, stateful=False))
model.add(layers.Dense(X_train.shape[1], input_shape=(1,), activation='linear'))
model.compile(optimizer=optimizers.Adam(lr=0.01, decay=0.008, amsgrad=True), loss='mean_squared_error', metrics=['mae'])


# construct a class for keras callbacks, to make sure the cell state is reset after each epoch
class ResetStatesAfterEachEpoch(Callback):
    def on_epoch_end(self, epoch, logs=None):
        self.model.reset_states()

reset_state = ResetStatesAfterEachEpoch()
callbacks = [reset_state]


# fit model to training data
history = model.fit(X_train, y_train, epochs=20000, batch_size=len(X_train),
                        shuffle=False, callbacks=callbacks)


# re-define LSTM model with weights of fit model to predict for 1 point, so also re-define the batch size to 1
new_batch_size = 1
new_model = models.Sequential()
new_model.add(layers.LSTM(1, batch_input_shape=(new_batch_size, X_test.shape[1], X_test.shape[2]), return_sequences=False,
                          stateful=False))
new_model.add(layers.Dense(X_test.shape[1], input_shape=(1,), activation='linear'))

# copy weights to new model
old_weights = model.get_weights()
new_model.set_weights(old_weights)


# single point prediction on train data
y_pred_train = new_model.predict(X_train, batch_size=new_batch_size)

# single point prediction on test data
y_pred_test = new_model.predict(X_test, batch_size=new_batch_size)

# plot predictions
plt.figure()
plt.plot(y_test, 'r', label='ground truth test',
         linestyle='dashed', linewidth=0.8)
plt.plot(y_train, 'b', label='ground truth train',
         linestyle='dashed', linewidth=0.8)
plt.plot(y_pred_test, 'g',
         label='y pred test', linestyle='dotted',
         linewidth=0.8)
plt.plot(y_pred_train, 'k',
         label='y pred train', linestyle='-.',
         linewidth=0.8)
plt.title('pred order: test, train')
plt.xlabel('time steps')
plt.ylabel('y')
plt.legend(prop={'size': 8})
plt.show()

Ответы [ 2 ]

0 голосов
/ 30 января 2020

так что я нашел решение, я не знаю, почему это работает (я был бы признателен, если бы кто-то сделал и мог оставить комментарий?), Но это работает.

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

x = np.sin(2 * np.pi * f * z / Fs)
dx_dt = np.cos(2 * np.pi * f * z / Fs)
X_train = np.column_stack((x, dx_dt))

Даже смещенный во времени y, такой как y_train = 5 * np.sin(2 * np.pi * f * (z + 51) / Fs), был предсказан довольно хорошо обученным с 3000 эпохами. LSTM 1 слой и 3 нейрона.

это результирующий сюжет .

0 голосов
/ 17 января 2020

Проблема здесь:

model.add(layers.LSTM(1, batch_input_shape=(len(X_train), X_train.shape[1], X_train.shape[2]),
                      return_sequences=False, stateful=True))

Вы устанавливаете stateful=True в слое LSTM, что означает, что скрытое состояние не сбрасывается после каждого прогноза, что объясняет эффект, который вы видите. Если вам не нужно это поведение, вы должны установить для него значение по умолчанию stateful=False, и оно будет работать как стандартный LSTM без сохранения состояния.

...