machine-learning - 使用 RNN 的非线性多元时间序列响应预测

标签 machine-learning time-series lstm prediction recurrent-neural-network

考虑到内部和外部气候,我试图预测墙壁的湿热响应。根据文献研究,我相信 RNN 应该可以做到这一点,但我无法获得很好的准确性。

该数据集有 12 个输入特征(外部和内部气候数据的时间序列)和 10 个输出特征(湿热响应的时间序列),均包含 10 年的每小时值。该数据是用湿热模拟软件创建的,没有丢失数据。

数据集特征: Input features

数据集目标: Output features

与大多数时间序列预测问题不同,我想预测每个时间步的输入特征时间序列的完整长度的响应,而不是时间序列的后续值(例如金融时间序列)预言)。我还没有找到类似的预测问题(在类似或其他领域),所以如果您知道,非常欢迎引用。

<小时/>

我认为这应该可以通过 RNN 实现,因此我目前正在使用 Keras 的 LSTM。在训练之前,我按以下方式预处理数据:

  1. 丢弃第一年的数据,因为墙体湿热响应的初始时间步长受到初始温度和相对湿度的影响。
  2. 分为训练集和测试集。训练集包含前8年的数据,测试集包含剩余2年的数据。
  3. 使用 Sklearn 的 StandardScaler 对训练集进行标准化(零均值,单位方差)。使用训练集的均值方差对测试集进行类似的归一化。

结果为:X_train.shape = (1, 61320, 12)y_train.shape = (1, 61320, 10)X_test。形状 = (1, 17520, 12), y_test.shape = (1, 17520, 10)

由于这些是较长的时间序列,因此我使用有状态 LSTM 并按照说明切割时间序列 here ,使用 stateful_cut() 函数。我只有 1 个样本,因此 batch_size 为 1。对于 T_after_cut 我尝试过 24 和 120 (24*5); 24 似乎给出了更好的结果。结果为 X_train.shape = (2555, 24, 12)y_train.shape = (2555, 24, 10)X_test.shape = (730 , 24, 12), y_test.shape = (730, 24, 10)

接下来,我按如下方式构建和训练 LSTM 模型:

model = Sequential()
model.add(LSTM(128, 
               batch_input_shape=(batch_size,T_after_cut,features), 
               return_sequences=True,
               stateful=True,
               ))
model.addTimeDistributed(Dense(targets)))
model.compile(loss='mean_squared_error', optimizer=Adam())

model.fit(X_train, y_train, epochs=100, batch_size=batch=batch_size, verbose=2, shuffle=False)

不幸的是,我没有得到准确的预测结果;即使对于训练集也是如此,因此该模型具有很高的偏差。

The prediction results of the LSTM model for all targets

<小时/>

如何改进我的模型?我已经尝试过以下操作:

  1. 不丢弃数据集的第一年 -> 没有显着差异
  2. 区分输入特征时间序列(从当前值中减去先前值)-> 结果稍差
  3. 最多四个堆叠 LSTM 层,全部具有相同的超参数 -> 结果没有显着差异,但训练时间更长
  4. LSTM 层之后的 Dropout 层(尽管这通常用于减少方差,并且我的模型具有较高偏差)-> 结果稍好,但差异可能不具有统计显着性

我对有状态 LSTM 做错了什么吗?我需要尝试不同的 RNN 模型吗?我应该以不同的方式预处理数据吗?

此外,训练速度非常慢:上面的模型大约需要 4 个小时。因此,我不愿意进行广泛的超参数网格搜索......

最佳答案

最后,我通过以下方式解决了这个问题:

  • 使用更多样本进行训练,而不是仅使用 1 个样本(我使用 18 个样本进行训练,6 个样本进行测试)
  • 保留第一年的数据,因为所有样本的输出时间序列都具有相同的“起点”,并且模型需要此信息来学习
  • 对输入和输出特征进行标准化(零均值、单位方差)。我发现这提高了预测准确性和训练速度
  • 按照描述使用有状态 LSTM here ,但在纪元之后添加重置状态(请参阅下面的代码)。我使用了 batch_size = 6T_after_cut = 1460。如果T_after_cut较长,则训练速度较慢;如果 T_after_cut 较短,准确性会略有下降。如果有更多样本可用,我认为使用较大的 batch_size 会更快。
  • 使用 CuDNNLSTM 代替 LSTM,这将训练时间加快 4 倍!
  • 我发现更多的单元可以带来更高的准确度和更快的收敛速度(更短的训练时间)。我还发现,对于相同数量的单元,GRU 与 LSTM 一样准确,收敛速度更快。
  • 监控训练期间的验证损失并使用提前停止

LSTM 模型的构建和训练如下:

def define_reset_states_batch(nb_cuts):
  class ResetStatesCallback(Callback):
    def __init__(self):
      self.counter = 0

    def on_batch_begin(self, batch, logs={}):
    # reset states when nb_cuts batches are completed
      if self.counter % nb_cuts == 0:
        self.model.reset_states()
      self.counter += 1

    def on_epoch_end(self, epoch, logs={}):
    # reset states after each epoch
      self.model.reset_states()
      return(ResetStatesCallback)    

model = Sequential()
model.add(layers.CuDNNLSTM(256, batch_input_shape=(batch_size,T_after_cut ,features),
  return_sequences=True,
  stateful=True))
model.add(layers.TimeDistributed(layers.Dense(targets, activation='linear')))

optimizer = RMSprop(lr=0.002)
model.compile(loss='mean_squared_error', optimizer=optimizer)

earlyStopping = EarlyStopping(monitor='val_loss', min_delta=0.005, patience=15, verbose=1, mode='auto')
ResetStatesCallback = define_reset_states_batch(nb_cuts)
model.fit(X_dev, y_dev, epochs=n_epochs, batch_size=n_batch, verbose=1, shuffle=False, validation_data=(X_eval,y_eval), callbacks=[ResetStatesCallback(), earlyStopping])

这给了我非常令人满意的准确度(R2 超过 0.98): Prediction 该图显示了 2 年来墙内的温度(左)和相对湿度(右)(训练中未使用的数据),预测为红色,真实输出为黑色。残差表明误差非常小,并且 LSTM 学会捕获长期依赖性来预测相对湿度。

关于machine-learning - 使用 RNN 的非线性多元时间序列响应预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48929272/

相关文章:

tensorflow - 如何处理keras中多元LSTM的多步时间序列预测

python - keras访问预训练模型的层参数以卡住

nlp - 无法设置属性 "trainable_weights",可能是因为它与现有的只读属性冲突

machine-learning - 多个二元分类器组合

python - 我可以从 ionic 应用程序访问 python 脚本吗

python-3.x - 使用 NLP 模型查找该语句中存在的特定对象

r - 如何在 R 中重新组合季节性分解的 STL 组件

python - 如何在Python中逐行遍历表格的列并将其放入列表中

python - Keras LSTM 训练。如何调整我的输入数据?

keras - keras 中二维元素的填充序列