长时间序列LSTM爆炸梯度

时间:2020-05-06 23:06:36

标签: keras deep-learning time-series lstm

我正尝试训练回溯约100步的时间序列预测模型。但是,当我第一次开始训练它时,损失总是微不足道的。我想仔细观察一下,发现即使是第一个预测(在进行任何学习之前,可能都是使用随机初始化的权重),所有值均为NaN。如果我减少回溯的次数,那么它几乎不会达到1e + 36左右,仍然很高,并且会引起爆炸性的梯度(我想,对这些术语还不是很熟悉。)

这是我的体系结构在代码中的外观:

model = Sequential()
model.add(TimeDistributed(Conv2D(filters=3, kernel_size=5, activation='relu', input_shape=(n_features, n_steps), data_format='channels_first')))
model.add(TimeDistributed(MaxPooling2D(pool_size=5, data_format='channels_first')))
model.add(TimeDistributed(Flatten()))
model.add(LSTM(128, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(outputs.shape[1]))
model.compile(optimizer='rmsprop', loss='mse')

还有形状,您可以从以下内容中看到: model

输入数据包括一些降水(大约50-150),温度(-10和25之间)和地下水位数据(100-500之间),输出包括对地下水位数据的预测。

在我看来,即使没有任何训练也很难获得nans或很高的数值,而且我不确定这是否称为爆炸梯度,我想知道我在这里做错了什么。

2 个答案:

答案 0 :(得分:0)

我建议您将输出标准化为(0.,1.),并在最后一层使用Sigmoid。

您始终可以使用逆变换来重建原始输出。

mn = np.min(y_train)
mx = np.max(y_train)
y_train = (y_train - mn)/(mx - mn)

# ... train

# inverse transform
y_train_original = y_train*(mx-mn) + mn

您的最后一层是linear,上一次激活是relu。您需要使用sigmoid裁剪输出。

  1. 将输出标准化为0-1范围。

  2. 在最后一层使用S形。 model.add(Dense(outputs.shape[1], activation = 'sigmoid'))

答案 1 :(得分:0)

我建议您首先删除以下三行,以查看模型的工作原理:

model.add(TimeDistributed(Conv2D(filters=3, kernel_size=5, activation='relu', input_shape=(n_features, n_steps), data_format='channels_first')))
model.add(TimeDistributed(MaxPooling2D(pool_size=5, data_format='channels_first')))
model.add(TimeDistributed(Flatten()))