考虑到内部和外部气候,我试图预测墙壁的湿热响应。根据文献研究,我相信 RNN 应该可以做到这一点,但我无法获得很好的准确性。
该数据集有 12 个输入特征(外部和内部气候数据的时间序列)和 10 个输出特征(湿热响应的时间序列),均包含 10 年的每小时值。该数据是用湿热模拟软件创建的,没有丢失数据。
与大多数时间序列预测问题不同,我想预测每个时间步的输入特征时间序列的完整长度的响应,而不是时间序列的后续值(例如金融时间序列)预言)。我还没有找到类似的预测问题(在类似或其他领域),所以如果您知道,非常欢迎引用。
<小时/>我认为这应该可以通过 RNN 实现,因此我目前正在使用 Keras 的 LSTM。在训练之前,我按以下方式预处理数据:
- 丢弃第一年的数据,因为墙体湿热响应的初始时间步长受到初始温度和相对湿度的影响。
- 分为训练集和测试集。训练集包含前8年的数据,测试集包含剩余2年的数据。
- 使用 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
<小时/>如何改进我的模型?我已经尝试过以下操作:
- 不丢弃数据集的第一年 -> 没有显着差异
- 区分输入特征时间序列(从当前值中减去先前值)-> 结果稍差
- 最多四个堆叠 LSTM 层,全部具有相同的超参数 -> 结果没有显着差异,但训练时间更长
- LSTM 层之后的 Dropout 层(尽管这通常用于减少方差,并且我的模型具有较高偏差)-> 结果稍好,但差异可能不具有统计显着性
我对有状态 LSTM 做错了什么吗?我需要尝试不同的 RNN 模型吗?我应该以不同的方式预处理数据吗?
此外,训练速度非常慢:上面的模型大约需要 4 个小时。因此,我不愿意进行广泛的超参数网格搜索......
最佳答案
最后,我通过以下方式解决了这个问题:
- 使用更多样本进行训练,而不是仅使用 1 个样本(我使用 18 个样本进行训练,6 个样本进行测试)
- 保留第一年的数据,因为所有样本的输出时间序列都具有相同的“起点”,并且模型需要此信息来学习
- 对输入和输出特征进行标准化(零均值、单位方差)。我发现这提高了预测准确性和训练速度
- 按照描述使用有状态 LSTM here ,但在纪元之后添加重置状态(请参阅下面的代码)。我使用了
batch_size = 6
和T_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):
该图显示了 2 年来墙内的温度(左)和相对湿度(右)(训练中未使用的数据),预测为红色,真实输出为黑色。残差表明误差非常小,并且 LSTM 学会捕获长期依赖性来预测相对湿度。
关于machine-learning - 使用 RNN 的非线性多元时间序列响应预测,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48929272/