基于RNN的非线性多元时间序列响应预测

Ast*_*rid 4 machine-learning time-series prediction lstm recurrent-neural-network

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

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

数据集功能: 输入功能

数据集目标: 输出功能

与大多数时间序列预测问题不同,我想在每个时间步长预测输入要素时间序列的全长响应,而不是时间序列的后续值(例如财务时间序列预测)。我还没有找到类似的预测问题(在相似或其他领域),因此,如果您知道其中一个,那么欢迎参考。


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

  1. 丢弃第一年的数据,因为壁的湿热响应的最初步骤受初始温度和相对湿度的影响。
  2. 分为训练和测试集。训练集包含前8年的数据,测试集包含其余2年的数据。
  3. 使用StandardScalerSklearn 归一化训练集(零均值,单位方差)。类似地使用均值与训练集的方差归一化测试集。

这导致:X_train.shape = (1, 61320, 12)y_train.shape = (1, 61320, 10)X_test.shape = (1, 17520, 12)y_test.shape = (1, 17520, 10)

由于这些都是较长的时间序列,因此我将使用有状态LSTM并按照此处的说明使用stateful_cut()函数削减时间序列。我只有1个样本,所以只有1个batch_size。因为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)
Run Code Online (Sandbox Code Playgroud)

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

LSTM模型对所有目标的预测结果


How can I improve my model? I have already tried the following:

  1. Not discarding the first year of the dataset -> no significant difference
  2. Differentiating the input features time-series (subtract previous value from current value) -> slightly worse results
  3. Up to four stacked LSTM layers, all with the same hyperparameters -> no significant difference in results but longer training time
  4. Dropout layer after LSTM layer (though this is usually used to reduce variance and my model has high bias) -> slightly better results, but difference might not be statistically significant

Am I doing something wrong with the stateful LSTM? Do I need to try different RNN models? Should I preprocess the data differently?

Furthermore, training is very slow: about 4 hours for the model above. Hence I am reluctant to do an extensive hyperparameter gridsearch...

Ast*_*rid 5

最后,我设法通过以下方式解决此问题:

  • 使用更多样本进行训练,而不是仅使用1个样本(我使用18个样本进行训练,使用6个样本进行测试)
  • 保留第一年的数据,因为所有样本的输出时间序列具有相同的“起点”,并且模型需要此信息来学习
  • 标准化输入和输出特征(零均值,单位方差)。我发现这提高了预测准确性和训练速度
  • 所描述的使用状态LSTM 这里,但时代的后面添加复位状态(参见下面的代码)。我曾经使用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])
Run Code Online (Sandbox Code Playgroud)

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