如何使用 Keras RNN 模型来预测未来的日期或事件?

Posted

技术标签:

【中文标题】如何使用 Keras RNN 模型来预测未来的日期或事件?【英文标题】:How to use a Keras RNN model to forecast for future dates or events? 【发布时间】:2018-07-23 10:46:55 【问题描述】:

这是我训练完整模型并保存它的代码:

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 天或一分钟的价格。

请给我建议出路。一个星期以来,我一直被这个问题困扰,无法进行任何成功的尝试。

这里是存储库的链接,在这里可以找到完整的可运行代码、模型和数据集:My repository link

【问题讨论】:

有人可以帮我解决这个问题吗?请告诉我。 我对数据集有疑问。您提供价格作为输入,说明您的模型有多准确。有更复杂的模型无法如此准确地预测进化。我猜第二个输入是日期(在头部不可见(第 3 块)?。我有时间会看看,但你可以看看这个视频(youtube.com/watch?v=EqWm8A-dRYg)。他正在预测 BTC 价格具有双向 LSTM 和社交网络情绪。最后,您可以预测之后的日子(因为您有每天的时间步长)。如果您需要模式天数,您可以创建一个循环。 @NicolasM.Sure.. 感谢您的时间和考虑。但是看看代码,这样我就可以改进了。谢谢。 为什么要投反对票?我不明白,为什么没有任何答案的人开始对问题投反对票,或者有时试图关闭它。 与您所做的相比,我稍微修改了数据框。尽管如此,我添加了一个移位列来预测下一个价格,但预测仍然准确。我不知道到底出了什么问题,但我想这是因为我们有 1 批大约 700 个时间步长的 1 个输入,并且模型能够理解只有一个转变。每次我尝试 RNN 时,与这个练习相比,我使用了多个批次,所以我也被卡住了:s。我会继续看看 【参考方案1】:

好吧,您需要一个stateful=True 模型,因此您可以一个接一个地为其提供预测以获得下一个预测,并让模型认为每个输入不是一个新序列,而是前一个序列的续集。

修复代码和培训

我在代码中看到有人试图让你的 y 成为一个 shifte 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)

因此,您显然只创建了 1 步的序列,这意味着您的 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

【讨论】:

这太棒了....丹尼尔。这很好,至少你试图帮助我......我会尝试你的建议,如果它有效,我也会接受你的回答。 亲爱的 Daniel,您是否可以在此处更改我的存储库代码:github.com/JafferWilson/forecastbtc 我想这会对我有很大帮助并让我理解.. 我正在尝试实现您的方式。不过可以试试看。 daniel 你检查过我的代码吗...因为在添加您的建议后我遇到了很多错误... regressor.add(LSTM(units = num_units, activation = activation_function, input_shape=(None, 1), stateful=True,return_sequences=True, batch_input_shape=(1, len(x_train), 1))) 我用 staeful=true 做了这样的代码 基本形状不匹配错误。 LSTM 层需要 3D 数据,你给它的是 2D 数据。【参考方案2】:

为了使用 RNN 预测未来值,您需要做的是提供数据作为序列。像这样的:

[0 1 2] --> [3]
[1 2 3] --> [4]
[2 3 4] --> [5]
[3 4 5] --> [6]
[4 5 6] --> [7]

RNN 学习序列的结构,因此需要独特的输入形状:

(n_samples, time_steps, n_features)

例如,如果您使用上周的每一天,时间步长可能是 7。

如何为 RNN 创建数据集?

    tf.keras.preprocessing.timeseries_dataset_from_array

您需要为该函数提供 a) 当前值和 b) 未来值。这里,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]
    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]]

【讨论】:

【参考方案3】:

在我的例子中,我在下面使用了这个代码,几乎没有修改。它工作正常。谢谢

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)

【讨论】:

以上是关于如何使用 Keras RNN 模型来预测未来的日期或事件?的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 LSTM Keras 预测未来库存

如何使用 LSTM 单元训练 RNN 以进行时间序列预测

在 R 中使用 RNN (Keras) 进行时间序列预测

LSTM模型(基于Keras框架)预测特定城市或者区域的太阳光照量实战

如何建立一个keras模型

如何将多个 CSV 数据集以适合 Keras 中的模型?