Вопрос или проблема
Я пытаюсь обучить модель на большом последовательном наборе данных, как этот [0.2 0.1 0.1 ..... 0.4 0.8]
. Я создаю векторы X длиной 60 для входных данных и скалярные числа Y в качестве меток (это значит, что LSTM читает первые 60 чисел как входные данные (одна строка в X_train) и 61-е число как выходную метку (строки в y_train)).
model = Sequential()
model.add(LSTM(units = 50, return_sequences = True , input_shape = (X_train.shape[1], 1)))
model.add(Dense(units = 1))
model.compile(optimizer="adam", loss="mean_squared_error")
model.fit(X_train, y_train, epochs = 100, batch_size = 32)
И:
X_train.shape = (1000,60,1) , y_train.shape = (1000,)
Здесь все в порядке, но проблема возникает в части предсказания. То, что я пытаюсь сделать, это создать вектор ввода (60*1) и использовать его для предсказания следующего числа в моей последовательности. Затем я добавляю новое предсказанное число в свою последовательность, чтобы предсказать следующее число (второе предсказанное число) и так далее. Для этой цели я создал новую модель, получил веса из предыдущей модели, а затем подал new_model только с одним вектором (60*1), чтобы предсказать следующее число. Затем я добавил предсказанное число в последовательность и сдвинул входные векторы на одно число вправо (чтобы использовать новое предсказанное число для предсказания следующего числа).
new_model = Sequential()
new_model.add(LSTM(units = 50, return_sequences = True , input_shape = (1 , 60 , 1 )))
new_model.add(Dense(1))
old_weights = model.get_weights()
new_model.set_weights(old_weights)
new_model.compile(optimizer="adam", loss="mean_squared_error")
inputs = []
for i in range(10):
inputs = dataset_total[len(dataset_total) - 60:].values
inputs = np.reshape(inputs, (1 , 60, 1))
predicted = new_model.predict(inputs)
inputs.append(predicted)
Но что я получаю – это такие ошибки:
ValueError: Input 0 is incompatible with layer lstm_61: expected
ndim=3, found ndim=4
Я не знаю, как решить эту проблему!
Здесь также есть аналогичный, но не связанный ответ (для пояснения):
Как предсказать будущие значения временного горизонта с помощью Keras?
Для вашей проблемы Keras сообщает вам, что вектор ввода имеет 4 измерения, что недопустимо, потому что для модели LSTM вам нужен вектор ввода с размерами (batch_size, num_time_steps, feature_space_dimension). Проверьте форму вектора ввода, возможно, вы добавляете дополнительное размерность с оператором reshape.
Еще одна вещь – это подход, который вы принимаете, который может быть действительным, но обычно эту проблему решают с помощью специфического типа моделей: моделей последовательности-в-последовательность, используя архитектуру LSTM энкодер-декодер.
Эти модели пытаются предсказать последовательность
$Y = [x_{(t=1)}, x_{(t=2)},…,x_{(t=t+N)}]$
из последовательности предыдущих значений
$X = [x_{(t=0)}, x_{(t=-1)},…,x_{(t=t-M)}]$
Обратите внимание, что количество образцов в каждой последовательности может быть разным.
В этих моделях входная последовательность $X$ подается в LSTM энкодер, который захватывает её динамику, создавая новый вектор контекста $F$. Этот новый вектор признаков затем подается декодеру LSTM как начальное состояние, а затем предсказание $\hat y(t)$ ячейки на время $t$ используется как вход для ячейки на время $t+1$, чтобы сгенерировать предсказанное значение $\hat y(t+1)$.
Одно ключевое отличие заключается в том, что модели Seq2seq должны быть более эффективными, чем ваш подход, поскольку они выполняют предсказание N будущих значений с одного запуска модели. Было бы интересно, если бы вы попробовали этот подход и сравнили его с вашим.
Вы можете посетить руководство Keras для этих типов моделей здесь.
Ответ или решение
Как добавлять предыдущие предсказания для новых предсказаний в LSTM
Если вы работаете с моделями временных рядов, такими как LSTM, одна из распространенных задач — это использование предсказанных значений в качестве входных данных для будущих предсказаний. В этой статье мы рассмотрим, как корректно реализовать этот процесс, а также научимся избегать распространенных ошибок.
Проблема
На основе вашего описания, вы столкнулись с ошибкой, связанной с несовпадением размерностей при передаче входных данных в модель. Вы пытались использовать предсказанные значения для создания нового входного вектора, однако столкнулись с ошибкой, подтверждающей, что размерности входных данных не соответствуют ожиданиям модели.
Решение проблемы с размерностью
Ошибка ValueError: Input 0 is incompatible with layer lstm_61: expected ndim=3, found ndim=4
указывает на то, что вы передали данные с четырьмя размерностями вместо требуемых трех. Давайте сначала разберемся с форматом входных данных для LSTM.
LSTM ожидает входные данные в формате (batch_size, num_time_steps, feature_dimension)
. Это означает, что для вашего случая с одним временным рядом, который вы будете использовать для предсказания, необходимо убедиться, что данные имеют следующую структуру:
- batch_size: количество образцов, передаваемых в модель одновременно (для вашего использования — это 1).
- num_time_steps: длина последовательности (у вас это 60).
- feature_dimension: количество признаков в каждой временной метке (в вашем случае — 1).
Если вы хотите добавить предсказанные значения к вашему входному вектору, используйте следующий алгоритм:
- Предскажите новое значение.
- Переместите существующие значения на одну позицию влево, добавив предсказанное значение в конец списка.
Пример кода:
import numpy as np
# Предположим, что dataset_total — это ваш массив с данными
inputs = dataset_total[-60:].values.reshape((1, 60, 1)) # Подготовка входов
predictions = []
for i in range(10): # Предсказание на 10 шагов вперед
predicted = new_model.predict(inputs) # Предсказываем следующее значение
predictions.append(predicted[0, 0]) # Сохраняем предсказанное значение в список
# Обновляем входные данные: сдвигаем значения влево и добавляем предсказанное значение
inputs = np.append(inputs[:, 1:, :], predicted.reshape((1, 1, 1)), axis=1)
print(predictions)
Подход Sequence-to-Sequence
На самом деле, более оптимальным подходом может стать использование модели Encoder-Decoder, известной как Sequence-to-Sequence (Seq2Seq). Эта архитектура позволяет не только предсказывать следующее значение, но и обрабатывать более сложные задачи, где требуется предсказание последовательностей.
Недостатки вашего текущего подхода:
- Каждый раз, когда вы используете предсказанное значение в качестве входного, происходит накопление ошибок.
- Большое количество итераций может привести к неэффективным вычислениям.
Используя Seq2Seq, вы можете более эффективно предсказывать несколько значений с одной пропускной способности через модель.
Примерная структура Seq2Seq могла бы выглядеть следующим образом:
- Создайте кодировщик (Encoder), который будет обрабатывать входную последовательность.
- Состояние кодировщика передается декодировщику (Decoder) для генерации предсказанных значений.
- Декодер генерирует последовательности, используя предсказанные значения в качестве нового состояния.
Вы можете найти обучающие материалы по Seq2Seq на официальном сайте Keras или их блоге. Это даст вам возможность лучше понять, как использовать LSTM для решения сложных задач предсказания временных рядов.
Заключение
Работа с LSTM и временными рядами подразумевает сложные шаги. Правильное обращение с размерностями входных данных — это лишь один из аспектов. Использование более совершенных архитектур, таких как Seq2Seq, может значительно повысить эффективность и точность ваших моделей. Не забывайте экспериментировать и исследовать новые подходы, чтобы находить лучшие решения для ваших задач.