如何在不减小网络规模的情况下使LSTM处理较长的输入样本?

问题描述

背景:

我正在使用LSTM(内置在tensorflow.js中)基于输入文本文件生成文本。我将文本文件拆分为样本,最初使每个样本的长度为10。然后将其缩放为20,一切都很好。最终,我将其放大到100,LSTM的梯度爆炸了,损失变成了NaN。

我尝试了梯度裁剪,梯度归一化,权重正则化,批量大小缩减,更改模型的体系结构……无济于事。

唯一有帮助的是减小LSTM的大小(从3 512层减少到3 64层),但是我希望我的模型保持其计算能力。

我的模型的结构如下:

//chars.length is how many unique characters are in the training set.
const model = tf.sequential({
    layers: [
        tf.layers.lstm({ inputShape: [null,chars.length],units: 512,activation: "relu",returnSequences: true }),tf.layers.lstm({ units: 512,returnSequences: false }),tf.layers.dense({ units: chars.length,activation: "softmax" }),]
});

然后,我以以下方式编译模型:

model.compile({
    optimizer: "adam",loss: "categoricalCrossentropy",metrics: ["accuracy"],clipValue: 0.5,clipnorm: 1,learningRate: 0.001
})

我已经检查了训练数据,并且所有数据都是有效的。

如果剪切,为什么我的LSTM梯度仍会爆炸?还有其他原因导致NaN损失吗?关于如何解决它的任何想法?

(常规的重量调整,减小批次大小和梯度修剪的方法无效。)

完整代码https://gist.github.com/N8python/22c42550ae1cf50236a4c63720cc3ee8

解决方法

您应该首先尝试对较短的序列进行训练,然后对逐渐较长的序列进行相同的权重相同的模型训练。如果使用长序列上随机初始化的权重来启动模型,则该模型往往不稳定。因此,我们可以使用在对较短序列进行训练之前获得的合理权重来启动模型,然后再移至较长序列。