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

How to get LSTM to handle long input samples, without reducing the size of the network?

背景:

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

我尝试了梯度裁剪、梯度归一化、权重正则化、批量大小缩减、改变我的模型的架构……都没有用。

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

我的模型结构如下:

//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, activation: "relu", returnSequences: true }),
        tf.layers.lstm({ units: 512, activation: "relu", 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 损失?关于如何修复它有什么想法吗?

(权重正则化、batch size缩减、梯度裁剪等常规方法无效。)

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

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