Keras LSTM предсказал, что таймеры сжимаются и смещаются

Я пытаюсь получить опыт работы с Keras во время каникул, и я подумал, что начну с примера учебника по прогнозированию таймсеров по данным запаса. Итак, что я пытаюсь сделать, даны последние 48 часов средних изменений цен (в процентах с предыдущих), предскажите, что такое средняя цена на следующий час.

Однако при проверке на тестовом наборе (или даже в наборе обучения) амплитуда предсказанной серии отходит, а иногда сдвигается так, чтобы она всегда была положительной или всегда отрицательной, т.е. Сдвигалась от 0% изменения, которое я думаю, было бы правильно для такого рода вещей.

Я привел следующий минимальный пример, чтобы показать проблему:

df = pandas.DataFrame.from_csv('test-data-01.csv', header=0)
df['pct'] = df.value.pct_change(periods=1)

seq_len=48
vals = df.pct.values[1:] # First pct change is NaN, skip it
sequences = []
for i in range(0, len(vals) - seq_len):
    sx = vals[i:i+seq_len].reshape(seq_len, 1)
    sy = vals[i+seq_len]
    sequences.append((sx, sy))

row = -24
trainSeqs = sequences[:row]
testSeqs = sequences[row:]

trainX = np.array([i[0] for i in trainSeqs])
trainy = np.array([i[1] for i in trainSeqs])

model = Sequential()
model.add(LSTM(25, batch_input_shape=(1, seq_len, 1)))
model.add(Dense(1))
model.compile(loss='mse', optimizer='adam')
model.fit(trainX, trainy, epochs=1, batch_size=1, verbose=1, shuffle=True)

pred = []
for s in trainSeqs:
    pred.append(model.predict(s[0].reshape(1, seq_len, 1)))
pred = np.array(pred).flatten()

plot(pred)
plot([i[1] for i in trainSeqs])
axis([2500, 2550,-0.03, 0.03])

Как вы можете видеть, я создаю тренировочные и тестовые последовательности, выбирая последние 48 часов и следующий шаг в кортеж, а затем продвигаясь на 1 час, повторяя процедуру. Модель представляет собой очень простой 1 LSTM и 1 плотный слой.

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

  • Оранжевый: истинные данные
  • Синий: прогнозируемые данные

enter image description here

Любая идея, что может быть? Я что-то неправильно понял?

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

plot(pred*12-0.03)
plot([i[1] for i in trainSeqs])
axis([2500, 2550,-0.03, 0.03])

enter image description here

Поскольку вы можете видеть, что предсказание прекрасно подходит к реальным данным, оно просто как-то раздавлено и компенсируется, и я не могу понять, почему.

Ответ 1

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

  • Уменьшение размера LSTM.
  • Добавление некоторой формы регуляризации для борьбы с переобучением. Например, исключение может быть хорошим выбором.
  • Обучение более эпохе или изменение скорости обучения. Для поиска подходящих параметров модели может потребоваться больше эпох или больших обновлений.

ОБНОВИТЬ. Позвольте мне обобщить то, что мы обсудили в разделе комментариев.

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

Если только последнее изменение цены действительно не очень информативно о будущем изменении цены, тогда:

  • Ваша модель научится прогнозировать среднее значение изменения цены (возможно, что-то около 0), так как это значение, которое дает самую низкую потерю при отсутствии информационных характеристик.
  • Предсказания могут показаться слегка "сдвинутыми", потому что изменение цены в timestep t + 1 слегка коррелирует с изменением цены по времени t (но все же предсказание чего-то близкого к 0 является самым безопасным выбором). Это действительно единственный образец, который я, как неопытный, мог бы наблюдать (т.е. Что значение в timestep t + 1 иногда похоже на значение по времени t).

Если значения в timesteps t и t + 1 оказались более коррелированными в целом, то я предполагаю, что модель будет более уверенно относиться к этой корреляции, и амплитуда предсказания будет больше.

Ответ 2

  1. Увеличьте количество эпох. Вы можете использовать EarlyStopping, чтобы избежать переобучения.
  2. Как ваши данные масштабируются? Временные ряды очень чувствительны к выбросам в данных. Например, попробуйте MinMax ((0.1, 0.9)), а затем RobustScaler также является хорошим выбором.
  3. Я не уверен, что LSTM (seq_len) действительно необходим, пока у вас не будет много данных. Почему бы не попробовать меньшее измерение?

Попробуйте все это и попробуйте переработать (mse должно быть около нуля в реальном наборе данных). Затем примените регуляризации.

ОБНОВИТЬ

Позвольте мне объяснить вам, почему вы

plot(pred*12-0.03)

хорошая посадка.

Хорошо, давайте рассмотрим слой LSTM как черный ящик и забудем об этом. Он возвращает нам 25 значений - это все. Это значение переходит к слою Dense, где мы применим к вектору функции 25 значений:

y = w * x + b

Здесь w и b - векторы, определенные в NN и в начале, обычно близки к нулю. x - ваши значения после слоя LSTM и y - target (одно значение).

Пока у вас всего 1 эпоха: w и b вообще не привязаны к вашим данным (они практически равны нулю). Но что, если вы примете

plot(pred*12-0.03)

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

Итак, увеличьте количество эпох, чтобы лучше подходить.

UPDATE2 Кстати, я вижу некоторые выбросы в данных. Вы можете также использовать MAE в качестве показателей потери/точности.