Как использовать модель Keras для прогнозирования будущих дат или событий?
Вот мой код для обучения всей модели и ее сохранения.
num_units = 2
activation_function = 'sigmoid'
optimizer = 'adam'
loss_function = 'mean_squared_error'
batch_size = 10
num_epochs = 100
# Initialize the RNN
regressor = Sequential()
# Adding the input layer and the LSTM layer
regressor.add(LSTM(units = num_units, activation = activation_function, input_shape=(None, 1)))
# Adding the output layer
regressor.add(Dense(units = 1))
# Compiling the RNN
regressor.compile(optimizer = optimizer, loss = loss_function)
# Using the training set to train the model
regressor.fit(x_train, y_train, batch_size = batch_size, epochs = num_epochs)
regressor.save('model.h5')
После этого я видел, что большую часть времени люди предлагали нам тестовый набор данных для проверки прогноза, который я тоже пытался и получил хороший результат.
Но проблема в использовании модели, которую я создал. Я хочу иметь прогноз на следующие 30 дней или каждую минуту вообще. Теперь у меня есть обученная модель, но я не понимаю, что я могу сделать или какой код использовать, чтобы использовать модель и прогнозировать цены на следующие 30 дней или одну минуту.
Пожалуйста, предложите мне выход. Я застрял в этой проблеме с недели и не в состоянии сделать какие-либо успешные попытки.
Вот ссылка на хранилище, где можно найти полный исполняемый код, модель и набор данных. Моя ссылка на хранилище
3 ответа
Ну нужен stateful=True
модель, так что вы можете передать ей один прогноз за другим, чтобы получить следующий и сохранить модель, думая, что каждый вход не новая последовательность, а продолжение предыдущего.
Исправление кода и обучение
Я вижу в коде, что есть попытка сделать ваш y
будь сдвигом x
(хороший вариант для прогнозирования следующих шагов). Но здесь также есть большая проблема при предварительной обработке:
training_set = df_train.values
training_set = min_max_scaler.fit_transform(training_set)
x_train = training_set[0:len(training_set)-1]
y_train = training_set[1:len(training_set)]
x_train = np.reshape(x_train, (len(x_train), 1, 1))
Данные для LSTM
слои должны быть в форме (number_of_sequences, number_of_steps,features)
,
Таким образом, вы четко создаете последовательности только из одного шага, а это означает, что ваш LSTM вообще не обучает последовательности. (Нет последовательности с одним шагом).
Предполагая, что ваши данные представляют собой единственную уникальную последовательность с 1 признаком, она определенно должна иметь форму (1, len(x_train), 1)
,
Естественно, y_train
также должен иметь такую же форму.
Это, в свою очередь, потребует, чтобы ваши слои LSTM были return_sequences=True
- единственный способ сделать y
иметь длину в шагах. Кроме того, для хорошего прогноза вам может понадобиться более сложная модель (потому что теперь она будет полностью изучена).
Сделав это, вы тренируете свою модель, пока не получите удовлетворительный результат.
Предсказывать будущее
Для предсказания будущего вам понадобится stateful=True
LSTM слои.
Прежде всего, вы сбрасываете состояния модели: model.reset_states()
- Необходим каждый раз, когда вы вводите новую последовательность в модель с состоянием.
Затем сначала вы прогнозируете весь X_train
(это необходимо для того, чтобы модель поняла, в какой точке последовательности она находится, технически говоря: для создания состояния).
predictions = model.predict(`X_train`) #this creates states
И, наконец, вы создаете цикл, в котором вы начинаете с последнего шага предыдущего прогноза:
future = []
currentStep = predictions[:,-1:,:] #last step from the previous prediction
for i in range(future_pred_count):
currentStep = model.predict(currentStep) #get the next step
future.append(currentStep) #store the future steps
#after processing a sequence, reset the states for safety
model.reset_states()
пример
Этот код делает это с последовательностью из 2-х элементов, смещенным предсказанием будущего шага и методом, который немного отличается от этого ответа, но основан на том же принципе.
Я создал две модели (одна stateful=False
, для тренировки без необходимости каждый раз сбрасывать состояния - никогда не забывайте сбрасывать состояния при запуске новой последовательности - и другие stateful=True
копирование весов из обученной модели, для предсказания будущего)
https://github.com/danmoller/TestRepo/blob/master/TestBookLSTM.ipynb
Что вам нужно сделать, чтобы предсказать будущие значения с помощью RNN, так это предоставить данные в виде последовательностей. Что-то вроде этого:
RNN изучают структуру последовательностей и поэтому нуждаются в уникальной входной форме:
(n_samples, time_steps, n_features)
Например, временные шаги могут быть равны 7, если вы используете каждый день последней недели.
Как я могу создать набор данных для RNN?
Что вам нужно сделать, так это предоставить этой функции а) текущие значения и б) будущие значения. Здесь,
seq_length
количество временных шагов для использования.
import tensorflow as tf
seq_length = 3
x = tf.range(25)[:-seq_length]
y = tf.range(25)[seq_length:]
ds = tf.keras.preprocessing.timeseries_dataset_from_array(x, y,
sequence_length=seq_length,
batch_size=1)
for present_values, next_value in ds.take(5):
print(tf.squeeze(present_values).numpy(), '-->', next_value.numpy())
[0 1 2] --> [3]
[1 2 3] --> [4]
[2 3 4] --> [5]
[3 4 5] --> [6]
[4 5 6] --> [7]
Вы также можете сделать то же самое для нескольких переменных:
import tensorflow as tf
seq_length = 3
x = tf.concat([
tf.reshape(tf.range(25, dtype=tf.float32)[:-seq_length], (-1, 1)),
tf.reshape(tf.linspace(0., .24, 25) [:-seq_length], (-1, 1))], axis=-1)
y = tf.concat([
tf.reshape(tf.range(25, dtype=tf.float32)[seq_length:], (-1, 1)),
tf.reshape(tf.linspace(0., .24, 25) [seq_length:], (-1, 1))], axis=-1)
ds = tf.keras.preprocessing.timeseries_dataset_from_array(x, y,
sequence_length=seq_length,
batch_size=1)
for present_values, next_value in ds.take(5):
print(tf.squeeze(present_values).numpy(), '-->', tf.squeeze(next_value).numpy())
model = tf.keras.Sequential([
tf.keras.layers.LSTM(8),
tf.keras.layers.Dense(8, activation='relu'),
tf.keras.layers.Dense(2)
])
model.compile(loss='mae', optimizer='adam')
history = model.fit(ds)
[[0. 0. ]
[1. 0.01]
[2. 0.02]] --> [3. 0.03]
[[1. 0.01]
[2. 0.02]
[3. 0.03]] --> [4. 0.04]
[[2. 0.02]
[3. 0.03]
[4. 0.04]] --> [5. 0.05]
[[3. 0.03]
[4. 0.04]
[5. 0.05]] --> [6. 0.06]
[[4. 0.04]
[5. 0.05]
[6. 0.06]] --> [7. 0.07]
- Эта функция
import tensorflow as tf
import numpy as np
x = np.arange(25)
def univariate_data(dataset, start_index, end_index, history_size, target_size):
data, labels = [], []
start_index = start_index + history_size
if end_index is None:
end_index = len(dataset) - target_size
for i in range(start_index, end_index):
indices = np.arange(i-history_size, i)
data.append(np.reshape(dataset[indices], (history_size, 1)))
labels.append(dataset[i:i+target_size])
return np.array(data), np.array(labels)
present_values, future_values = univariate_data(x, 0, 9, 3, 3)
for present, next_val in zip(present_values, future_values):
print(tf.squeeze(present).numpy(), '-->', tf.squeeze(next_val).numpy())
[0 1 2] --> [3 4]
[1 2 3] --> [4 5]
[2 3 4] --> [5 6]
[3 4 5] --> [6 7]
[4 5 6] --> [7 8]
[5 6 7] --> [8 9]
А теперь для нескольких переменных:
import tensorflow as tf
import numpy as np
history_size = 3
x = np.concatenate([np.expand_dims(np.arange(25), 1)[:-history_size],
np.expand_dims(np.linspace(0., .24, 25), 1)[:-history_size]], axis=1)
y = np.concatenate([np.expand_dims(np.arange(25), 1)[history_size:],
np.expand_dims(np.linspace(0., .24, 25), 1)[history_size:]], axis=1)
def multivariate_data(dataset, target, start_index, end_index, history_size,
target_size, step, single_step=False):
data = []
labels = []
start_index = start_index + history_size
if end_index is None:
end_index = len(dataset) - target_size
for i in range(start_index, end_index):
indices = range(i-history_size, i, step)
data.append(dataset[indices])
if single_step:
labels.append(target[i+target_size])
else:
labels.append(target[i:i+target_size])
return np.array(data), np.array(labels)
present_values, future_values = multivariate_data(x, y, 0, 8, history_size, 1, 1)
for present, next_val in zip(present_values, future_values):
print(tf.squeeze(present).numpy(), '-->', tf.squeeze(next_val).numpy())
[[0. 0. ]
[1. 0.01]
[2. 0.02]] --> [6. 0.06]
[[1. 0.01]
[2. 0.02]
[3. 0.03]] --> [7. 0.07]
[[2. 0.02]
[3. 0.03]
[4. 0.04]] --> [8. 0.08]
[[3. 0.03]
[4. 0.04]
[5. 0.05]] --> [9. 0.09]
[[4. 0.04]
[5. 0.05]
[6. 0.06]] --> [10. 0.1]
import tensorflow as tf
import numpy as np
history_size = 3
lookahead = 2
x = tf.range(8)
ds = tf.data.Dataset.from_tensor_slices(x)
ds = ds.window(history_size + lookahead, shift=1, drop_remainder=True)
ds = ds.flat_map(lambda window: window.batch(history_size + lookahead))
ds = ds.map(lambda window: (window[:-lookahead], window[-lookahead:]))
for present_values, next_value in ds:
print(present_values.numpy(), '-->', next_value.numpy())
[0 1 2] --> [3 4]
[1 2 3] --> [4 5]
[2 3 4] --> [5 6]
[3 4 5] --> [6 7]
С несколькими переменными:
import tensorflow as tf
import numpy as np
history_size = 3
lookahead = 2
x = tf.concat([
tf.reshape(tf.range(20, dtype=tf.float32), (-1, 1)),
tf.reshape(tf.linspace(0., .19, 20), (-1, 1))], axis=-1)
ds = tf.data.Dataset.from_tensor_slices(x)
ds = ds.window(history_size + lookahead, shift=1, drop_remainder=True)
ds = ds.flat_map(lambda window: window.batch(history_size + lookahead))
ds = ds.map(lambda window: (window[:-lookahead], window[-lookahead:]))
for present_values, next_value in ds.take(8):
print(tf.squeeze(np.round(present_values, 2)).numpy(), '-->',
tf.squeeze(np.round(next_value, 2)).numpy())
print()
[[0. 0. ]
[1. 0.01]
[2. 0.02]] --> [[3. 0.03]
[4. 0.04]]
[[1. 0.01]
[2. 0.02]
[3. 0.03]] --> [[4. 0.04]
[5. 0.05]]
[[2. 0.02]
[3. 0.03]
[4. 0.04]] --> [[5. 0.05]
[6. 0.06]]
[[3. 0.03]
[4. 0.04]
[5. 0.05]] --> [[6. 0.06]
[7. 0.07]]
[[4. 0.04]
[5. 0.05]
[6. 0.06]] --> [[7. 0.07]
[8. 0.08]]
[[5. 0.05]
[6. 0.06]
[7. 0.07]] --> [[8. 0.08]
[9. 0.09]]
Я использовал этот код с небольшими изменениями ниже в моем случае. Это работает нормально. Спасибо
future_pred_count=10
future = []
currentStep = np.array([187, 196, 210])
for i in range(future_pred_count):
prediction = model.predict(currentStep[np.newaxis, :, np.newaxis]) # set dimentions
future.append(prediction[0][0])
currentStep = np.append(currentStep[1:], prediction[0][0], axis=None ) #store the future steps
print(future)