我正尝试训练回溯约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')
输入数据包括一些降水(大约50-150),温度(-10和25之间)和地下水位数据(100-500之间),输出包括对地下水位数据的预测。
在我看来,即使没有任何训练也很难获得nans或很高的数值,而且我不确定这是否称为爆炸梯度,我想知道我在这里做错了什么。
答案 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
裁剪输出。
将输出标准化为0-1
范围。
在最后一层使用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()))