Как использовать модель 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?

  1. tf.keras.preprocessing.timeseries_dataset_from_array

Что вам нужно сделать, так это предоставить этой функции а) текущие значения и б) будущие значения. Здесь, 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]
  1. Эта функция
      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]
  1. tf.data.Dataset.window
      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)
Другие вопросы по тегам