Keras - 摘要直方图LSTM中的NaN

3

我使用Keras编写了一个LSTM模型,并使用了LeakyReLU高级激活函数:

    # ADAM Optimizer with learning rate decay
    opt = optimizers.Adam(lr=0.0001, beta_1=0.9, beta_2=0.999, epsilon=1e-08, decay=0.0001)

    # build the model
    model = Sequential()

    num_features = data.shape[2]
    num_samples = data.shape[1]

    model.add(
        LSTM(16, batch_input_shape=(None, num_samples, num_features), return_sequences=True, activation='linear'))
    model.add(LeakyReLU(alpha=.001))
    model.add(Dropout(0.1))
    model.add(LSTM(8, return_sequences=True, activation='linear'))
    model.add(Dropout(0.1))
    model.add(LeakyReLU(alpha=.001))
    model.add(Flatten())
    model.add(Dense(1, activation='sigmoid'))

    model.compile(loss='binary_crossentropy', optimizer=opt,
                  metrics=['accuracy', keras_metrics.precision(), keras_metrics.recall(), f1])

我的数据是一个二分类平衡标记集,即:50%标为1,50%标为0。 我在LSTM层之前使用了activation='linear',这与我在GitHub上找到的此示例类似,用于LeakyReLU激活。

在该配置下,模型抛出Nan in summary histogram错误。将LSTM激活函数更改为activation='sigmoid'可以正常运行,但似乎不是正确的做法。

阅读这个StackOverflow问题建议“在计算损失时引入小值”,我只是不确定如何在内置损失函数上实现它。

任何帮助/说明将不胜感激。

更新: 我可以看到第一次epoch上损失为nan。

260/260 [==============================] - 6s 23ms/step - 
loss: nan - acc: 0.5000 - precision: 0.5217 - recall: 0.6512 - f1: nan - val_loss: nan - val_acc: 0.0000e+00 - val_precision: -2147483648.0000 - val_recall: -49941480.1860 - val_f1: nan

更新2 我已将TensorFlow和Keras升级到版本1.12.0和2.2.4。但是效果并没有改善。

我还尝试了像@Oluwafemi Sule建议的在第一个LSTM层中添加损失,这看起来是朝着正确方向迈出的一步,现在第一个epoch的损失不再是nan,但是我仍然遇到了相同的错误...可能是因为其他nan值,比如val_loss/val_f1。

[==============================] - 7s 26ms/step - 
loss: 1.9099 - acc: 0.5077 - precision: 0.5235 - recall: 0.6544 - f1: 0.5817 - val_loss: nan - val_acc: 0.5172 - val_precision: 35.0000 - val_recall: 0.9722 - val_f1: nan

更新3 我尝试只使用准确性指标编译网络,但没有成功。

Epoch 1/300
260/260 [==============================] - 8s 29ms/step - loss: nan - acc: 0.5538 - val_loss: nan - val_acc: 0.0000e+00

我曾经遇到过类似的问题,但是我的数据集中存在 NaN 值导致出现了问题。 - kerastf
1
我不确定你的梯度是否爆炸,因为仅仅使用LeakyRelu是不足以使其收敛的。但通常有一个选项叫做'clipnorm'或者'clipvalue',你可以将其与所有优化器一起传递。这有助于剪裁梯度,并且通常用于找到摆脱局部最小值的方法。你可以在这里尝试一下,看看是否有任何区别?来源 - kvish
@ShlomiSchwartz 你尝试过升级TensorFlow和Keras并查看问题是否仍然存在吗?如果是,那么请尝试使用Adam优化器默认参数,并修改学习率。尝试使用1e-31e-41e-5作为学习率。另外,您是否尝试使用clipnorm来裁剪梯度。此外,请在评论开头使用@用户名回复特定用户,否则该用户将不会收到有关您的评论的通知(我没有收到您之前的评论通知,我只是偶然查看了这个问题并看到您已经回答)。 - today
2
@ShlomiSchwartz 只需将clipnorm=1.0参数传递给优化器,例如Adam(..., clipnorm=1.0) - today
当您从LeakyReLUs增加参数alpha(例如到0.3)时会发生什么? - rvinas
显示剩余9条评论
1个回答

3
这个答案从建议“在计算损失时引入一个小值”开始。
像所有直接或间接继承自 keras.engine.base_layer.Layer 的层一样,keras.layers.LSTM具有一个add_loss方法,可以用来设置损失的起始值。
我建议为LSTM层执行此操作,并查看它是否对您的结果产生任何影响。
lstm_layer = LSTM(8, return_sequences=True, activation='linear')
lstm_layer.add_loss(1.0)

model.add(lstm_layer)

感谢您的回答。看起来是朝着正确方向迈出的一步,现在在第一个时期,我可以看到 260/260 [==============================] - 7s 26ms/step - loss: 1.9099 - acc: 0.5077 - precision: 0.5235 - recall: 0.6544 - f1: 0.5817 - val_loss: nan - val_acc: 0.5172 - val_precision: 35.0000 - val_recall: 0.9722 - val_f1: nan。所以损失不再是nan,但是我仍然得到相同的错误...可能是因为其他nan值,比如val_loss / val_f1? - Shlomi Schwartz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接