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

Python 如何使用Keras RNN模型预测未来日期或事件?,python,tensorflow,keras,Python,Tensorflow,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 re

以下是我训练完整模型并保存它之前的代码:

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

请告诉我出去的路。我一个星期以来一直在解决这个问题,没能做出任何成功的尝试


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

好吧,您需要一个
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
层的数据必须成形为
(序列的数量、步骤的数量、特征)

因此,很明显,您只创建了一个步骤的序列,这意味着您的LSTM根本没有学习序列。(没有只包含一个步骤的序列)

假设您的数据是一个具有1个特征的唯一序列,那么它的形状肯定应该是
(1,len(x_train),1)

当然,
y_train
也应该具有相同的形状

反过来,这将要求您的LSTM层为
return\u sequences=True
——这是使
y
具有步长长度的唯一方法。此外,为了进行良好的预测,您可能需要一个更复杂的模型(因为现在它将是真正的学习)

完成后,您将训练您的模型,直到获得满意的结果


预测未来

为了预测未来,您需要
stateful=True
LSTM层

在进行任何操作之前,先重置模型的状态:
model.reset_states()
——每次将新序列输入到有状态模型时都需要重置

然后,首先预测整个
X_序列
(这是模型理解序列的哪一点所必需的,用技术术语来说:创建状态)

最后创建一个循环,从上一个预测的最后一步开始:

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()

示例

这段代码使用两个特征序列、一个移动的未来步长预测和一种与此答案稍有不同但基于相同原理的方法来实现这一点

我创建了两个模型(一个是
stateful=False
,用于训练而无需每次重置状态-在开始新序列时不要忘记重置状态-另一个是
stateful=True
,复制训练模型的权重,用于预测未来)


在我的案例中,我使用了这段代码,但在下面做了一些修改。它很好用。谢谢

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)

为了使用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创建数据集?
  • 您需要做的是为该函数提供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())
    
    您也可以对多个变量执行相同的操作:

    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)
    
    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())
    
    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()
    
  • 此函数
  • 现在,对于多个变量:

    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)
    
    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())
    
    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()
    
  • 具有多个变量:

    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)
    
    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())
    
    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()
    

    有人能帮我解决这个问题吗?请让我知道。我对数据集有疑问。您提供价格作为输入,解释模型的准确性。还有更多的复杂模型无法如此精确地预测进化。我猜第二个输入是日期(在头部不可见(块3)?。我有时间时会看一看,但你可以看一下这段视频()。他用双向LSTM和社交网络情绪预测BTC价格。最后,你可以预测之后的几天(因为你有一个每日时间步)。如果您需要模式天数,您可以创建一个循环。@NicolasM。当然。。谢谢您的时间和考虑。但是,请看一下代码,以便我可以改进。谢谢。为什么要向下投票?我不明白,为什么没有任何答案的人开始向下投票这个问题,或者有时尝试关闭它。与您所做的相比,我稍微修改了数据框ne。尽管如此,我添加了一个移位列来预测下一个价格,但预测仍然是准确的。我不知道到底哪里错了,但我想这是因为我们有一批大约700个时间步的1个输入,模型能够理解只有一个移位。每次我尝试RNN,我都使用多个批次’s与这个练习相比,我也陷入了困境:s.我会继续看一看这太棒了……丹尼尔。这太棒了,至少你尝试过帮助我……我会尝试你的建议,如果它奏效,我也会接受你的答案。亲爱的丹尼尔,你有可能在我的存储库代码中进行更改吗:我想这会对我有很大帮助,我会e理解..我正在尝试实现你的方式。但是可以尝试一下。丹尼尔让你检查了我的代码…因为在添加你的建议后,我得到了很多错误…
    regressor.add(LSTM)(units=num\u units,activation=activation\u function,input\u shape=(无
    
    [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]]